]> git.saurik.com Git - apple/configd.git/commitdiff
configd-596.12.tar.gz os-x-109 os-x-1091 v596.12
authorApple <opensource@apple.com>
Tue, 29 Oct 2013 00:03:35 +0000 (00:03 +0000)
committerApple <opensource@apple.com>
Tue, 29 Oct 2013 00:03:35 +0000 (00:03 +0000)
171 files changed:
IPMonitorLogging.mobileconfig [new file with mode: 0644]
Makefile
Plugins/IPMonitor/Info.plist
Plugins/IPMonitor/Makefile
Plugins/IPMonitor/com.apple.networking.IPMonitor [new file with mode: 0644]
Plugins/IPMonitor/dns-configuration.c
Plugins/IPMonitor/dns-configuration.h
Plugins/IPMonitor/ip_plugin.c
Plugins/IPMonitor/ip_plugin.h [new file with mode: 0644]
Plugins/IPMonitor/proxy-configuration.c
Plugins/IPMonitor/proxy-configuration.h
Plugins/IPMonitor/set-hostname.c
Plugins/IPMonitor/set-hostname.h
Plugins/IPMonitor/smb-configuration.c
Plugins/IPMonitor/smb-configuration.h
Plugins/IPMonitor/test_ipv4_routelist_filter.sh
Plugins/IPMonitor/test_ipv4_routelist_reference.txt
Plugins/IPMonitor/test_reference.sh
Plugins/InterfaceNamer/Info.plist
Plugins/InterfaceNamer/ifnamer.c
Plugins/KernelEventMonitor/Info.plist
Plugins/KernelEventMonitor/ev_dlil.c
Plugins/KernelEventMonitor/ev_dlil.h
Plugins/KernelEventMonitor/ev_ipv4.h
Plugins/KernelEventMonitor/ev_ipv6.c
Plugins/KernelEventMonitor/ev_ipv6.h
Plugins/KernelEventMonitor/eventmon.c
Plugins/KernelEventMonitor/eventmon.h
Plugins/LinkConfiguration/Info.plist
Plugins/LinkConfiguration/linkconfig.c
Plugins/Logger/Info-Embedded.plist
Plugins/Logger/Info.plist
Plugins/Logger/logger.c
Plugins/PreferencesMonitor/Info.plist
Plugins/PreferencesMonitor/prefsmon.c
Plugins/SCNetworkReachability/Info.plist
Plugins/SimulatorSupport/Info.plist [new file with mode: 0644]
Plugins/SimulatorSupport/simulator_support.c [new file with mode: 0644]
Plugins/common/IPMonitorControlPrefs.c [new file with mode: 0644]
Plugins/common/IPMonitorControlPrefs.h [new file with mode: 0644]
SCMonitor/Info.plist
SCMonitor/monitor.c
SystemConfiguration.fproj/BondConfiguration.c
SystemConfiguration.fproj/BridgeConfiguration.c
SystemConfiguration.fproj/CaptiveNetwork.c
SystemConfiguration.fproj/CaptiveNetwork.h
SystemConfiguration.fproj/English.lproj/NetworkInterface.strings
SystemConfiguration.fproj/Info-Embedded.plist
SystemConfiguration.fproj/Info.plist
SystemConfiguration.fproj/LinkConfiguration.c
SystemConfiguration.fproj/LinkConfiguration.h [deleted file]
SystemConfiguration.fproj/SCD.c
SystemConfiguration.fproj/SCDNotifierInformViaCallback.c
SystemConfiguration.fproj/SCDOpen.c
SystemConfiguration.fproj/SCDPlugin.c
SystemConfiguration.fproj/SCDPrivate.c
SystemConfiguration.fproj/SCDynamicStoreCopyDHCPInfo.h
SystemConfiguration.fproj/SCDynamicStoreInternal.h
SystemConfiguration.fproj/SCDynamicStorePrivate.h
SystemConfiguration.fproj/SCNetworkConfigurationInternal.c
SystemConfiguration.fproj/SCNetworkConfigurationInternal.h
SystemConfiguration.fproj/SCNetworkConfigurationPrivate.h
SystemConfiguration.fproj/SCNetworkConnection.c
SystemConfiguration.fproj/SCNetworkConnectionInternal.h [new file with mode: 0644]
SystemConfiguration.fproj/SCNetworkConnectionPrivate.c
SystemConfiguration.fproj/SCNetworkConnectionPrivate.h
SystemConfiguration.fproj/SCNetworkInterface.c
SystemConfiguration.fproj/SCNetworkReachability.c
SystemConfiguration.fproj/SCNetworkReachabilityInternal.h
SystemConfiguration.fproj/SCNetworkService.c
SystemConfiguration.fproj/SCNetworkSet.c
SystemConfiguration.fproj/SCNetworkSignature.c
SystemConfiguration.fproj/SCNetworkSignature.h
SystemConfiguration.fproj/SCNetworkSignaturePrivate.h
SystemConfiguration.fproj/SCPCommit.c
SystemConfiguration.fproj/SCPOpen.c
SystemConfiguration.fproj/SCPPath.c
SystemConfiguration.fproj/SCPreferencesInternal.h
SystemConfiguration.fproj/SCPreferencesPrivate.h
SystemConfiguration.fproj/SCPrivate.h
SystemConfiguration.fproj/SCProxies.c
SystemConfiguration.fproj/SCSchemaDefinitions.c
SystemConfiguration.fproj/SCSchemaDefinitions.h
SystemConfiguration.fproj/SCSchemaDefinitionsPrivate.h
SystemConfiguration.fproj/SNHelper.c [new file with mode: 0644]
SystemConfiguration.fproj/SNHelperPrivate.h [new file with mode: 0644]
SystemConfiguration.fproj/SystemConfiguration.h
SystemConfiguration.fproj/VLANConfiguration.c
SystemConfiguration.fproj/VPNAppLayer.c [new file with mode: 0644]
SystemConfiguration.fproj/VPNAppLayerPrivate.h [new file with mode: 0644]
SystemConfiguration.fproj/VPNConfiguration.c
SystemConfiguration.fproj/VPNConfiguration.h
SystemConfiguration.fproj/VPNFlow.c [new file with mode: 0644]
SystemConfiguration.fproj/VPNFlow.h [new file with mode: 0644]
SystemConfiguration.fproj/VPNFlowPrivate.h [new file with mode: 0644]
SystemConfiguration.fproj/VPNPrivate.c
SystemConfiguration.fproj/VPNService.c [new file with mode: 0644]
SystemConfiguration.fproj/VPNTunnel.c
SystemConfiguration.fproj/VPNTunnel.h
SystemConfiguration.fproj/VPNTunnelPrivate.h
SystemConfiguration.fproj/config_types.h
SystemConfiguration.fproj/dy_framework.c
SystemConfiguration.fproj/dy_framework.h
SystemConfiguration.fproj/genSCPreferences.c
SystemConfiguration.fproj/helper/SCHelper_server.c
SystemConfiguration.fproj/helper/com.apple.SCHelper-embedded.plist
SystemConfiguration.fproj/helper/com.apple.SCHelper.plist
SystemConfiguration.fproj/reachability/SCNetworkReachabilityServer_client.c
SystemConfiguration.fproj/reachability/SCNetworkReachabilityServer_server.c
SystemConfiguration.fproj/reachability/rb.c [deleted file]
SystemConfiguration.fproj/reachability/rb.h [deleted file]
SystemConfiguration.fproj/scprefs_observer.c [new file with mode: 0644]
SystemConfiguration.fproj/scprefs_observer.h [new file with mode: 0644]
SystemConfiguration.fproj/update-headers
configd.tproj/_SCD.c
configd.tproj/_configadd.c
configd.tproj/_configclose.c
configd.tproj/_confignotify.c
configd.tproj/_configremove.c
configd.tproj/_configset.c
configd.tproj/_notifyremove.c
configd.tproj/com.apple.configd.plist
configd.tproj/com.apple.configd_sim.plist [new file with mode: 0644]
configd.tproj/configd.8
configd.tproj/configd.m
configd.tproj/configd_server.c
configd.tproj/entitlements.plist
configd.tproj/pattern.c
configd.tproj/pattern.h
configd.tproj/plugin_support.c
configd.tproj/session.c
configd.tproj/session.h
configd.xcodeproj/project.pbxproj
dnsinfo/dnsinfo.h
dnsinfo/dnsinfo_copy.c
dnsinfo/dnsinfo_create.c
dnsinfo/dnsinfo_create.h
dnsinfo/dnsinfo_flatfile.c
dnsinfo/dnsinfo_internal.h [new file with mode: 0644]
dnsinfo/dnsinfo_private.c [deleted file]
dnsinfo/dnsinfo_private.h
dnsinfo/dnsinfo_server.c
dnsinfo/dnsinfo_server.h
dnsinfo/shared_dns_info.defs [deleted file]
dnsinfo/shared_dns_info_types.h [deleted file]
get-mobility-info
libSystemConfiguration/libSystemConfiguration_client.c [new file with mode: 0644]
libSystemConfiguration/libSystemConfiguration_client.h [new file with mode: 0644]
libSystemConfiguration/libSystemConfiguration_server.c [new file with mode: 0644]
libSystemConfiguration/libSystemConfiguration_server.h [new file with mode: 0644]
nwi/network_information.c
nwi/network_information.h
nwi/network_information_priv.c
nwi/network_information_priv.h
nwi/network_information_server.c [new file with mode: 0644]
nwi/network_information_server.h [new file with mode: 0644]
scselect.tproj/scselect.c
scutil.tproj/cache.c
scutil.tproj/nc.c
scutil.tproj/net_interface.c
scutil.tproj/net_set.c
scutil.tproj/notifications.c
scutil.tproj/prefs.c
scutil.tproj/prefs.h
scutil.tproj/scutil.8
scutil.tproj/scutil.c
scutil.tproj/scutil.h
scutil.tproj/tests.c
scutil.tproj/tests.h
tests/Makefile [new file with mode: 0644]
tests/ReachabilityTester.c [new file with mode: 0644]

diff --git a/IPMonitorLogging.mobileconfig b/IPMonitorLogging.mobileconfig
new file mode 100644 (file)
index 0000000..6599da7
--- /dev/null
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>PayloadContent</key>
+       <array>
+               <dict>
+                       <key>PayloadDescription</key>
+                       <string>Enables IPMonitor verbose logging.</string>
+                       <key>PayloadDisplayName</key>
+                       <string>IPMonitor Logging</string>
+                       <key>PayloadIdentifier</key>
+                       <string>com.apple.defaults.managed.IPMonitor.control</string>
+                       <key>PayloadOrganization</key>
+                       <string>Apple, Inc</string>
+                       <key>PayloadType</key>
+                       <string>com.apple.defaults.managed</string>
+                       <key>PayloadUUID</key>
+                       <string>CA2DD325-2123-487C-BF89-170AF64FD8C0</string>
+                       <key>PayloadVersion</key>
+                       <integer>1</integer>
+                       <key>PayloadContent</key>
+                       <array>
+                               <dict>
+                                       <key>DefaultsDomainName</key>
+                                       <string>com.apple.IPMonitor.control</string>
+                                       <key>DefaultsData</key>
+                                       <dict>
+                                               <key>Verbose</key>
+                                               <true/>
+                                       </dict>
+                               </dict>
+                       </array>
+               </dict>
+       </array>
+       <key>PayloadDescription</key>
+       <string>Enables IPMonitor verbose logging.</string>
+       <key>PayloadDisplayName</key>
+       <string>IPMonitor Logging</string>
+       <key>PayloadIdentifier</key>
+       <string>com.apple.IPMonitor.control</string>
+       <key>PayloadOrganization</key>
+       <string>Apple, Inc</string>
+       <key>PayloadType</key>
+       <string>Configuration</string>
+       <key>PayloadUUID</key>
+       <string>CA2DD325-2123-487C-BF89-170AF64FD8C0</string>
+       <key>PayloadVersion</key>
+       <integer>1</integer>
+</dict>
+</plist>
index af81588b7b52bc164ebd8520d91e9bff4b43f65a..79147d2e00ac266f5efef7d21d906e64a9bc3efa 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -43,6 +43,8 @@ LION_CFLAGS+=-D__MAC_10_8=1070
 LION_CFLAGS+=-D__AVAILABILITY_INTERNAL__MAC_10_8=__attribute__((visibility(\\\"default\\\")))
 LION_CFLAGS+=-DHAVE_REACHABILITY_SERVER=YES
 
+LION_SDKROOT=$(shell xcodebuild -version -sdk macosx10.7internal Path)
+
 lion :
        /usr/local/bin/buildit .                                \
          -noinstallsrc -noinstallhdrs -noverify -nosum         \
@@ -52,4 +54,6 @@ lion :
          -configuration Debug                                  \
          -release $(shell cat /usr/share/buildit/.releaseName) \
          -othercflags "$(LION_CFLAGS)"                         \
+         --                                                    \
+         SDKROOT=$(LION_SDKROOT)                               \
 
index 09072ba96636eac58767c20203bd318e180bd6ee..91375dbac8e7857de55475fc4f20e1c844ba11ee 100644 (file)
        <key>CFBundlePackageType</key>
        <string>BNDL</string>
        <key>CFBundleShortVersionString</key>
-       <string>1.12.2</string>
+       <string>1.13</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>1.12.2</string>
+       <string>1.13</string>
        <key>Requires</key>
        <array>
                <string>com.apple.SystemConfiguration.IPConfiguration</string>
index 5b0750cf85c6dadb77b7d4e77e374280938762a5..41bb9103663dd576fcb05c717cca00c68dc5ade3 100644 (file)
@@ -1,58 +1,78 @@
 EXTRA_CFLAGS=
 
-all: test_proxy
+TEST_INCLUDE=-I. -I../common -I../../dnsinfo -I../../nwi -I../../libSystemConfiguration -I../../SystemConfiguration.fproj
 
-# ----------
-
-shared_dns_info.h shared_dns_infoUser.c: ../../dnsinfo/shared_dns_info.defs
-       mig ../../dnsinfo/shared_dns_info.defs
+all: test_ipv4_routelist
 
-shared_dns_infoUser.o: shared_dns_info.h shared_dns_infoUser.c
-       cc -I../../dnsinfo -Wall -O0 -g -c shared_dns_infoUser.c
+# ----------
 
-dnsinfo_create.o: shared_dns_info.h ../../dnsinfo/dnsinfo_create.h ../../dnsinfo/dnsinfo_create.c
-       cc -I. -I../../dnsinfo -I../../nwi -Wall -O0 -g -c ../../dnsinfo/dnsinfo_create.c
+dnsinfo_create.o: ../../dnsinfo/dnsinfo_create.h ../../dnsinfo/dnsinfo_create.c
+       cc ${TEST_INCLUDE} -Wall -O0 -g -c ../../dnsinfo/dnsinfo_create.c
 
-dnsinfo_flatfile.o: ../../dnsinfo/dnsinfo_copy.c ../../dnsinfo/dnsinfo_flatfile.c shared_dns_info.h
-       cc -I../../dnsinfo -I../../nwi -D_PATH_RESOLVER_DIR='"/var/tmp/resolver"' -Wall -O0 -g -c ../../dnsinfo/dnsinfo_flatfile.c
+dnsinfo_flatfile.o: ../../dnsinfo/dnsinfo_copy.c ../../dnsinfo/dnsinfo_flatfile.c
+       cc ${TEST_INCLUDE} -D_PATH_RESOLVER_DIR='"/var/tmp/resolver"' -Wall -O0 -g -c ../../dnsinfo/dnsinfo_flatfile.c
 
-dnsinfo_private.o: ../../dnsinfo/dnsinfo_private.h ../../dnsinfo/dnsinfo_private.c
-       cc -I../../dnsinfo -Wall -O0 -g -c ../../dnsinfo/dnsinfo_private.c
+dnsinfo_server.o: ../../dnsinfo/dnsinfo_copy.c ../../dnsinfo/dnsinfo_server.c
+       cc ${TEST_INCLUDE} -Wall -O0 -g -c ../../dnsinfo/dnsinfo_server.c
 
 dns-configuration.o: dns-configuration.h dns-configuration.c dnsinfo_create.o
-       cc -I. -I../../dnsinfo -I../../nwi -DMAIN -Wall -O0 -g -c dns-configuration.c
+       cc ${TEST_INCLUDE} ${EXTRA_CFLAGS} -Wall -O0 -g -c dns-configuration.c
 
 network_information_priv.o: ../../nwi/network_information_priv.h ../../nwi/network_information_priv.c
-       cc -I. -I../../dnsinfo -I../../nwi -DMAIN -Wall -O0 -g -c ../../nwi/network_information_priv.c
+       cc ${TEST_INCLUDE} -Wall -O0 -g -c ../../nwi/network_information_priv.c
+
+network_information_server.o: ../../nwi/network_information_server.h ../../nwi/network_information_server.c
+       cc ${TEST_INCLUDE} -Wall -O0 -g -c ../../nwi/network_information_server.c
 
 proxy-configuration.o: proxy-configuration.h proxy-configuration.c
-       cc -I. -Wall -O0 -g -c proxy-configuration.c
+       cc ${TEST_INCLUDE} -Wall -O0 -g -c proxy-configuration.c
+
+set-hostname.o: set-hostname.c
+       cc ${TEST_INCLUDE} -Wall -O0 -g -c set-hostname.c
 
 smb-configuration.o: smb-configuration.c
-       cc -I. -Wall -O0 -g -c smb-configuration.c
+       cc ${TEST_INCLUDE} -Wall -O0 -g -c smb-configuration.c
+
+libSystemConfiguration_client.o: ../../libSystemConfiguration/libSystemConfiguration_client.h ../../libSystemConfiguration/libSystemConfiguration_client.c
+       cc ${TEST_INCLUDE} -Wall -O0 -g -c ../../libSystemConfiguration/libSystemConfiguration_client.c
+
+libSystemConfiguration_server.o: ../../libSystemConfiguration/libSystemConfiguration_server.h ../../libSystemConfiguration/libSystemConfiguration_server.c
+       cc ${TEST_INCLUDE} -Wall -O0 -g -c ../../libSystemConfiguration/libSystemConfiguration_server.c
+
+IPMonitorControlPrefs.o: ../common/IPMonitorControlPrefs.h ../common/IPMonitorControlPrefs.c
+       cc ${TEST_INCLUDE} -Wall -O0 -g -c ../common/IPMonitorControlPrefs.c
 
 # ----------
 
-test_dns: Makefile dnsinfo_create.o dnsinfo_flatfile.o dnsinfo_private.o shared_dns_infoUser.o dns-configuration.o
-       cc -o test_dns dnsinfo_create.o dnsinfo_flatfile.o dnsinfo_private.o shared_dns_infoUser.o dns-configuration.o ${EXTRA_CFLAGS} -framework SystemConfiguration -framework CoreFoundation
+dns-configurationX.o: dns-configuration.h dns-configuration.c dnsinfo_create.o
+       cc -DMAIN ${TEST_INCLUDE} ${EXTRA_CFLAGS} -Wall -O0 -g -c -o dns-configurationX.o dns-configuration.c
+
+ip_pluginX.o: ip_plugin.c
+       cc ${TEST_INCLUDE} ${EXTRA_CFLAGS} -Wall -O0 -g -c -o ip_pluginX.o ip_plugin.c
+
+test_dns: Makefile dnsinfo_create.o dnsinfo_flatfile.o dnsinfo_server.o ip_pluginX.o IPMonitorControlPrefs.o network_information_priv.o network_information_server.o dns-configurationX.o proxy-configuration.o set-hostname.o smb-configuration.o libSystemConfiguration_client.o libSystemConfiguration_server.o
+       cc -Wall -O0 -g -o test_dns dnsinfo_create.o dnsinfo_flatfile.o dnsinfo_server.o ip_pluginX.o IPMonitorControlPrefs.o network_information_priv.o network_information_server.o dns-configurationX.o proxy-configuration.o set-hostname.o smb-configuration.o libSystemConfiguration_client.o libSystemConfiguration_server.o ${EXTRA_CFLAGS} -framework SystemConfiguration -framework CoreFoundation
 
 # ----------
 
 test_proxy: Makefile proxy-configuration.h proxy-configuration.c
-       cc -Wall -O0 -g -o test_proxy -DMAIN -DDEBUG proxy-configuration.c ${EXTRA_CFLAGS} -framework SystemConfiguration -framework CoreFoundation
+       cc -DMAIN -DDEBUG -Wall -O0 -g -o test_proxy proxy-configuration.c ${EXTRA_CFLAGS} -framework SystemConfiguration -framework CoreFoundation
 
 # ----------
 
-test_smb: Makefile smb-configuration.h smb-configuration.c
-       cc -Wall -O0 -g -o test_smb -DMAIN -DDEBUG smb-configuration.c ${EXTRA_CFLAGS} -framework SystemConfiguration -framework CoreFoundation
+smb-configurationX.o: smb-configuration.h smb-configuration.c
+       cc -DMAIN ${TEST_INCLUDE} ${EXTRA_CFLAGS} -Wall -O0 -g -c -o smb-configurationX.o smb-configuration.c
+
+test_smb: Makefile dnsinfo_create.o dnsinfo_flatfile.o dnsinfo_server.o ip_pluginX.o IPMonitorControlPrefs.o network_information_priv.o network_information_server.o dns-configuration.o smb-configurationX.o proxy-configuration.o set-hostname.o libSystemConfiguration_client.o libSystemConfiguration_server.o
+       cc -Wall -O0 -g -o test_smb dnsinfo_create.o dnsinfo_flatfile.o dnsinfo_server.o ip_pluginX.o IPMonitorControlPrefs.o network_information_priv.o network_information_server.o dns-configuration.o smb-configurationX.o proxy-configuration.o set-hostname.o libSystemConfiguration_client.o libSystemConfiguration_server.o ${EXTRA_CFLAGS} -framework SystemConfiguration -framework CoreFoundation
 
 # ----------
 
 test_ipv4_routelist.o: ip_plugin.c
-       cc -I. -I../../dnsinfo -I../../nwi -DTEST_IPV4_ROUTELIST -Wall -O0 -g -c -o test_ipv4_routelist.o ip_plugin.c
+       cc -DTEST_IPV4_ROUTELIST ${TEST_INCLUDE} ${EXTRA_CFLAGS} -Wall -O0 -g -c -o test_ipv4_routelist.o ip_plugin.c
 
-test_ipv4_routelist: test_ipv4_routelist.o dnsinfo_create.o dnsinfo_flatfile.o dnsinfo_private.o shared_dns_infoUser.o network_information_priv.o smb-configuration.o proxy-configuration.o
-       cc -Wall -O0 -g -o test_ipv4_routelist test_ipv4_routelist.o dnsinfo_create.o dnsinfo_flatfile.o dnsinfo_private.o network_information_priv.o shared_dns_infoUser.o smb-configuration.o proxy-configuration.o -framework SystemConfiguration -framework CoreFoundation
+test_ipv4_routelist: test_ipv4_routelist.o IPMonitorControlPrefs.o dnsinfo_create.o dnsinfo_flatfile.o dnsinfo_server.o network_information_priv.o network_information_server.o smb-configuration.o proxy-configuration.o libSystemConfiguration_server.o
+       cc -Wall -O0 -g -o test_ipv4_routelist test_ipv4_routelist.o IPMonitorControlPrefs.o dnsinfo_create.o dnsinfo_flatfile.o dnsinfo_server.o network_information_priv.o network_information_server.o smb-configuration.o proxy-configuration.o libSystemConfiguration_server.o ${EXTRA_CFLAGS} -framework SystemConfiguration -framework CoreFoundation
 
 test_ipv4_routelist_reference.txt: test_ipv4_routelist
        sh test_reference.sh create test_ipv4_routelist test_ipv4_routelist_reference.txt test_ipv4_routelist_filter.sh
@@ -63,16 +83,15 @@ test_ipv4_routelist_test: test_ipv4_routelist
 # ----------
 
 IPMonitor.o: ip_plugin.c
-       cc -I. -I../../dnsinfo -I../../nwi -DTEST_IPMONITOR -Wall -O0 -g -c -o IPMonitor.o ip_plugin.c
+       cc -DTEST_IPMONITOR ${TEST_INCLUDE} ${EXTRA_CFLAGS} -Wall -O0 -g -c -o IPMonitor.o ip_plugin.c
 
-IPMonitor: IPMonitor.o dnsinfo_create.o dnsinfo_flatfile.o dnsinfo_private.o shared_dns_infoUser.o smb-configuration.o
-       cc -Wall -O0 -g -o IPMonitor IPMonitor.o dnsinfo_create.o dnsinfo_flatfile.o dnsinfo_private.o shared_dns_infoUser.o smb-configuration.o -framework SystemConfiguration -framework CoreFoundation
+IPMonitor: IPMonitor.o IPMonitorControlPrefs.o dnsinfo_create.o dnsinfo_flatfile.o dnsinfo_server.o network_information_priv.o network_information_server.o proxy-configuration.o smb-configuration.o libSystemConfiguration_client.o libSystemConfiguration_server.o
+       cc -Wall -O0 -g -o IPMonitor IPMonitor.o IPMonitorControlPrefs.o dnsinfo_create.o dnsinfo_flatfile.o dnsinfo_server.o network_information_priv.o network_information_server.o proxy-configuration.o smb-configuration.o libSystemConfiguration_client.o libSystemConfiguration_server.o ${EXTRA_CFLAGS} -framework SystemConfiguration -framework CoreFoundation
 
 # ----------
 
 clean:
        rm -rf  *.o                                                             \
-               shared_dns_info.h shared_dns_infoServer.c shared_dns_infoUser.c \
                test_dns test_dns.dSYM                                          \
                test_proxy test_proxy.dSYM                                      \
                test_smb test_smb.dSYM                                          \
diff --git a/Plugins/IPMonitor/com.apple.networking.IPMonitor b/Plugins/IPMonitor/com.apple.networking.IPMonitor
new file mode 100644 (file)
index 0000000..2f4a10a
--- /dev/null
@@ -0,0 +1 @@
+? [= LoggerID com.apple.networking.IPMonitor] file /Library/Logs/CrashReporter/com.apple.networking.IPMonitor.log crashlog rotate=local file_max=1M compress format=$((Time)(local.6))\ $Host\ $(Sender)[$(PID)]\ <$((Level)(str))>:\ $(Message)
index bd20b75b326d984fadb6173c1aaddcfba4d6745e..5815609c8387fbdac6955f583507fd4274e5cd10 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2012 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -51,16 +51,20 @@ extern uint32_t notify_monitor_file(int token, const char *name, int flags);
 #include <SystemConfiguration/SystemConfiguration.h>
 #include <SystemConfiguration/SCPrivate.h>
 #include <SystemConfiguration/SCValidation.h>
+#include "ip_plugin.h"
 
 #include "dns-configuration.h"
 
 #include <dnsinfo.h>
-#include <dnsinfo_create.h>
+#include "dnsinfo_create.h"
+#include "dnsinfo_server.h"
 
 #ifdef MAIN
 #undef MAIN
 #include "dnsinfo_copy.c"
+#include "dnsinfo_internal.h"
 #define        MAIN
+#define        DNS_CONFIGURATION_DEBUG
 #endif // MAIN
 
 #include <dns_sd.h>
@@ -82,6 +86,119 @@ static      CFNumberRef     S_mdns_timeout  = NULL;
 static CFNumberRef     S_pdns_timeout  = NULL;
 
 
+#pragma mark -
+#pragma mark DNS resolver flags
+
+
+static __inline__ boolean_t
+dns_resolver_flags_all_queries(uint32_t query_flags)
+{
+       return ((query_flags & DNS_RESOLVER_FLAGS_REQUEST_ALL_RECORDS) == DNS_RESOLVER_FLAGS_REQUEST_ALL_RECORDS);
+}
+
+
+
+
+static void
+add_dns_query_flags(const void *key, const void *value, void *context)
+{
+       CFDictionaryRef service         = value;
+       uint32_t        *query_flags    = context;
+
+
+       // check if the service has v4 or v6 configured
+
+       if ((*query_flags & DNS_RESOLVER_FLAGS_REQUEST_A_RECORDS) == 0) {
+               CFDictionaryRef v4_dict;
+
+               v4_dict = CFDictionaryGetValue(service, kSCEntNetIPv4);
+               if (v4_dict != NULL) {
+                       CFDictionaryRef v4_service;
+
+                       v4_service = CFDictionaryGetValue(v4_dict, kIPv4DictService);
+                       if (isA_CFDictionary(v4_service)) {
+                               CFArrayRef      if_addrs;
+                               CFBooleanRef    is_null;
+
+                               is_null = CFDictionaryGetValue(v4_service, kIsNULL);
+                               if_addrs = CFDictionaryGetValue(v4_service, kSCPropNetIPv4Addresses);
+                               if (isA_CFBoolean(is_null) != NULL && CFBooleanGetValue(is_null)) {
+                                       // ignore this service
+                               }
+                               else if (isA_CFArray(if_addrs) != NULL) {
+                                       int     i;
+                                       int     count;
+
+                                       count = CFArrayGetCount(if_addrs);
+                                       for (i = 0; i < count; i++) {
+                                               CFStringRef     if_addr;
+                                               struct in_addr  v4_addr;
+
+                                               if_addr = CFArrayGetValueAtIndex(if_addrs, i);
+                                               if (isA_CFString(if_addr) == NULL) {
+                                                       continue;
+                                               }
+
+                                               cfstring_to_ip(if_addr, &v4_addr);
+                                               if (!IN_LINKLOCAL(ntohl(v4_addr.s_addr))) {
+                                                       // set the request v4 dns record bit
+                                                       *query_flags |= DNS_RESOLVER_FLAGS_REQUEST_A_RECORDS;
+                                                       break;
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
+       if ((*query_flags & DNS_RESOLVER_FLAGS_REQUEST_AAAA_RECORDS) == 0) {
+               CFDictionaryRef v6_dict;
+
+               v6_dict = CFDictionaryGetValue(service, kSCEntNetIPv6);
+               if (isA_CFDictionary(v6_dict) != NULL) {
+                       CFArrayRef      if_addrs6;
+                       CFBooleanRef    is_null;
+
+                       is_null = CFDictionaryGetValue(v6_dict, kIsNULL);
+                       if_addrs6 = CFDictionaryGetValue(v6_dict, kSCPropNetIPv6Addresses);
+                       if (isA_CFBoolean(is_null) != NULL && CFBooleanGetValue(is_null)) {
+                               // ignore this service
+                       }
+                       else if (isA_CFArray(if_addrs6) != NULL) {
+                               int     i;
+                               int     count;
+
+                               count = CFArrayGetCount(if_addrs6);
+                               for (i = 0; i < count; i++) {
+                                       CFStringRef     if_addr6;
+                                       struct in6_addr v6_addr;
+
+                                       if_addr6 = CFArrayGetValueAtIndex(if_addrs6, i);
+                                       if (isA_CFString(if_addr6) == NULL) {
+                                               continue;
+                                       }
+
+                                       cfstring_to_ip6(if_addr6, &v6_addr);
+                                       if (!IN6_IS_ADDR_LINKLOCAL(&v6_addr)
+                                           && !IN6_IS_ADDR_MC_LINKLOCAL(&v6_addr)) {
+                                               // set the request v6 dns record bit
+                                               *query_flags |= DNS_RESOLVER_FLAGS_REQUEST_AAAA_RECORDS;
+                                               break;
+                                       }
+                               }
+                       }
+               }
+       }
+
+
+       return;
+}
+
+
+#pragma mark -
+#pragma mark DNS resolver configuration
+
+
 static void
 add_resolver(CFMutableArrayRef resolvers, CFMutableDictionaryRef resolver)
 {
@@ -93,7 +210,7 @@ add_resolver(CFMutableArrayRef resolvers, CFMutableDictionaryRef resolver)
 
        order = CFDictionaryGetValue(resolver, kSCPropNetDNSSearchOrder);
        if (!isA_CFNumber(order) ||
-           !CFNumberGetValue(order, kCFNumberIntType, &order_val)) {
+           !CFNumberGetValue(order, kCFNumberSInt32Type, &order_val)) {
                order     = NULL;
                order_val = 0;
        }
@@ -123,7 +240,7 @@ add_resolver(CFMutableArrayRef resolvers, CFMutableDictionaryRef resolver)
                                // if only the search order's are different
                                match_order = CFDictionaryGetValue(match_resolver, kSCPropNetDNSSearchOrder);
                                if (!isA_CFNumber(match_order) ||
-                                   !CFNumberGetValue(match_order, kCFNumberIntType, &match_order_val)) {
+                                   !CFNumberGetValue(match_order, kCFNumberSInt32Type, &match_order_val)) {
                                        match_order_val = 0;
                                }
 
@@ -142,7 +259,7 @@ add_resolver(CFMutableArrayRef resolvers, CFMutableDictionaryRef resolver)
        CFRelease(order);
 
        interface = CFDictionaryGetValue(resolver, kSCPropInterfaceName);
-       if (interface != NULL) {
+       if ((interface != NULL) && !CFEqual(interface, CFSTR("*"))) {
                uint32_t        flags;
                unsigned int    if_index                = 0;
                char            if_name[IF_NAMESIZE];
@@ -258,7 +375,11 @@ add_supplemental(CFMutableArrayRef resolvers, CFDictionaryRef dns, uint32_t defa
 
 
 static void
-add_supplemental_resolvers(CFMutableArrayRef resolvers, CFDictionaryRef services, CFArrayRef service_order)
+add_supplemental_resolvers(CFMutableArrayRef   resolvers,
+                          CFDictionaryRef      services,
+                          CFArrayRef           service_order,
+                          CFStringRef          scoped_interface,
+                          CFDictionaryRef      scoped_service)
 {
        const void *            keys_q[N_QUICK];
        const void **           keys    = keys_q;
@@ -282,19 +403,59 @@ add_supplemental_resolvers(CFMutableArrayRef resolvers, CFDictionaryRef services
 
        CFDictionaryGetKeysAndValues(services, keys, vals);
        for (i = 0; i < n_services; i++) {
-               uint32_t        defaultOrder;
-               CFDictionaryRef dns;
-               CFDictionaryRef service = (CFDictionaryRef)vals[i];
+               uint32_t                defaultOrder;
+               CFDictionaryRef         dns;
+               CFStringRef             interface;
+               uint32_t                interface_flags;
+               CFMutableDictionaryRef  newDNS          = NULL;
+               CFDictionaryRef         service         = (CFDictionaryRef)vals[i];
 
                if (!isA_CFDictionary(service)) {
                        continue;
                }
 
                dns = CFDictionaryGetValue(service, kSCEntNetDNS);
-               if (!isA_CFDictionary(dns)) {
+               dns = isA_CFDictionary(dns);
+               if (dns == NULL) {
                        continue;
                }
 
+               interface = CFDictionaryGetValue(dns, kSCPropInterfaceName);
+
+               if (scoped_interface != NULL) {
+                       //
+                       // we only want to add split/supplemental configurations
+                       // for queries scoped to an interface if they are NOT
+                       // associated with a "real" service
+                       //
+                       if (CFDictionaryContainsKey(service, kSCEntNetIPv4) ||
+                           CFDictionaryContainsKey(service, kSCEntNetIPv6)) {
+                               continue;
+                       }
+
+                       //
+                       // in addition, we don't want to add split/supplemental
+                       // configurations for queries scoped to an interface if
+                       // the configuration does not apply to all interfaces and
+                       // the configuration is explicitly NOT for this interface
+                       //
+                       if (!_SC_CFEqual(interface, CFSTR("*")) &&
+                           !_SC_CFEqual(interface, scoped_interface)) {
+                               continue;
+                       }
+
+                       //
+                       // lastly, check if A/AAAA queries should be issued (based
+                       // on the IP[v6] addresses).  If we would not be issuing a
+                       // query then don't bother adding the configuration.
+                       //
+                       interface_flags = 0;
+                       add_dns_query_flags(NULL, scoped_service, &interface_flags);
+                       if (interface_flags == 0) {
+                               continue;
+                       }
+               }
+
                defaultOrder = DEFAULT_SEARCH_ORDER
                               - (DEFAULT_SEARCH_ORDER / 2)
                               + ((DEFAULT_SEARCH_ORDER / 1000) * i);
@@ -304,7 +465,52 @@ add_supplemental_resolvers(CFMutableArrayRef resolvers, CFDictionaryRef services
                        defaultOrder += (DEFAULT_SEARCH_ORDER / 1000) * n_services;
                }
 
-               add_supplemental(resolvers, dns, defaultOrder);
+               /*
+                * Ensure that we have the correct InterfaceName in the DNS configuration
+                *
+                * scoped_interface     [supplemental] interface        DNS interface
+                * ================     ========================        =================
+                * NULL                 NULL                            NULL (No change)
+                * NULL                 en0                             NULL
+                * NULL                 *                               NULL
+                * en0                  NULL                            "en0"
+                * en0                  en0                             "en0" (now mutable)
+                * en0                  *                               "en0"
+                */
+               if ((scoped_interface == NULL) && (interface == NULL)) {
+                       newDNS = (CFMutableDictionaryRef)CFRetain(dns);
+               } else {
+                       newDNS = CFDictionaryCreateMutableCopy(NULL, 0, dns);
+                       if (scoped_interface != NULL) {
+                               CFDictionarySetValue(newDNS, kSCPropInterfaceName, scoped_interface);
+                       } else {
+                               CFDictionaryRemoveValue(newDNS, kSCPropInterfaceName);
+                       }
+               }
+
+               if (scoped_interface != NULL) {
+                       uint32_t        flags;
+                       CFNumberRef     num;
+
+                       // set "scoped" configuration flag(s)
+                       if (!CFDictionaryGetValueIfPresent(newDNS, DNS_CONFIGURATION_FLAGS_KEY, (const void **)&num) ||
+                           !isA_CFNumber(num) ||
+                           !CFNumberGetValue(num, kCFNumberSInt32Type, &flags)) {
+                               flags = 0;
+                       }
+                       flags |= DNS_RESOLVER_FLAGS_SCOPED;
+
+                       // add A/AAAA query flag(s)
+                       flags |= interface_flags;
+
+                       num = CFNumberCreate(NULL, kCFNumberSInt32Type, &flags);
+                       CFDictionarySetValue(newDNS, DNS_CONFIGURATION_FLAGS_KEY, num);
+                       CFRelease(num);
+               }
+
+               // add [scoped] resolver entry
+               add_supplemental(resolvers, newDNS, defaultOrder);
+               CFRelease(newDNS);
        }
 
        if (keys != keys_q) {
@@ -416,13 +622,13 @@ compareBySearchOrder(const void *val1, const void *val2, void *context)
 
        num1 = CFDictionaryGetValue(dns1, kSCPropNetDNSSearchOrder);
        if (!isA_CFNumber(num1) ||
-           !CFNumberGetValue(num1, kCFNumberIntType, &order1)) {
+           !CFNumberGetValue(num1, kCFNumberSInt32Type, &order1)) {
                order1 = DEFAULT_SEARCH_ORDER;
        }
 
        num2 = CFDictionaryGetValue(dns2, kSCPropNetDNSSearchOrder);
        if (!isA_CFNumber(num2) ||
-           !CFNumberGetValue(num2, kCFNumberIntType, &order2)) {
+           !CFNumberGetValue(num2, kCFNumberSInt32Type, &order2)) {
                order2 = DEFAULT_SEARCH_ORDER;
        }
 
@@ -432,8 +638,8 @@ compareBySearchOrder(const void *val1, const void *val2, void *context)
                    CFDictionaryGetValueIfPresent(dns2, DNS_CONFIGURATION_ORDER_KEY, (const void **)&num2) &&
                    isA_CFNumber(num1) &&
                    isA_CFNumber(num2) &&
-                   CFNumberGetValue(num1, kCFNumberIntType, &order1) &&
-                   CFNumberGetValue(num2, kCFNumberIntType, &order2)) {
+                   CFNumberGetValue(num1, kCFNumberSInt32Type, &order1) &&
+                   CFNumberGetValue(num2, kCFNumberSInt32Type, &order2)) {
                        if (order1 == order2) {
                                return kCFCompareEqualTo;
                        } else {
@@ -467,7 +673,7 @@ extract_search_domains(CFMutableDictionaryRef defaultDomain, CFArrayRef suppleme
 
                num = CFDictionaryGetValue(defaultDomain, kSCPropNetDNSSearchOrder);
                if (!isA_CFNumber(num) ||
-                   !CFNumberGetValue(num, kCFNumberIntType, &defaultOrder)) {
+                   !CFNumberGetValue(num, kCFNumberSInt32Type, &defaultOrder)) {
                        defaultOrder = DEFAULT_SEARCH_ORDER;
                }
 
@@ -578,6 +784,7 @@ extract_search_domains(CFMutableDictionaryRef defaultDomain, CFArrayRef suppleme
        for (i = 0; i < n_supplemental; i++) {
                CFDictionaryRef dns;
                CFIndex         domainIndex;
+               int             noSearch;
                CFNumberRef     num;
                CFStringRef     options;
                CFStringRef     supplementalDomain;
@@ -607,6 +814,14 @@ extract_search_domains(CFMutableDictionaryRef defaultDomain, CFArrayRef suppleme
                        continue;
                }
 
+               num = CFDictionaryGetValue(dns, kSCPropNetDNSSupplementalMatchDomainsNoSearch);
+               if (isA_CFNumber(num) &&
+                   CFNumberGetValue(num, kCFNumberIntType, &noSearch) &&
+                   (noSearch != 0)) {
+                       CFRelease(supplementalDomain);
+                       continue;
+               }
+
                if (CFStringHasSuffix(supplementalDomain, CFSTR(".in-addr.arpa")) ||
                    CFStringHasSuffix(supplementalDomain, CFSTR(".ip6.arpa"    ))) {
                        CFRelease(supplementalDomain);
@@ -619,7 +834,7 @@ extract_search_domains(CFMutableDictionaryRef defaultDomain, CFArrayRef suppleme
 
                num = CFDictionaryGetValue(dns, kSCPropNetDNSSearchOrder);
                if (!isA_CFNumber(num) ||
-                   !CFNumberGetValue(num, kCFNumberIntType, &supplementalOrder)) {
+                   !CFNumberGetValue(num, kCFNumberSInt32Type, &supplementalOrder)) {
                        supplementalOrder = DEFAULT_SEARCH_ORDER;
                }
 
@@ -681,7 +896,7 @@ add_scoped_resolvers(CFMutableArrayRef scoped, CFDictionaryRef services, CFArray
        n_order = isA_CFArray(service_order) ? CFArrayGetCount(service_order) : 0;
        if (n_order > 0) {
                order = CFArrayCreateMutableCopy(NULL, 0, service_order);
-       } else{
+       } else {
                order = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
        }
 
@@ -714,6 +929,7 @@ add_scoped_resolvers(CFMutableArrayRef scoped, CFDictionaryRef services, CFArray
                CFArrayRef              searchDomains;
                CFDictionaryRef         service;
                CFStringRef             serviceID;
+               uint32_t                these_flags;
 
                serviceID = CFArrayGetValueAtIndex(order, i);
                service = CFDictionaryGetValue(services, serviceID);
@@ -729,10 +945,16 @@ add_scoped_resolvers(CFMutableArrayRef scoped, CFDictionaryRef services, CFArray
                }
 
                interface = CFDictionaryGetValue(dns, kSCPropInterfaceName);
-               if (interface == NULL) {
-                       // if no [scoped] interface
+               if ((interface == NULL) || CFEqual(interface, CFSTR("*"))) {
+                       // if no [scoped] interface or supplemental configuration w/match-all
+                       continue;
+               }
+
+               if (CFDictionaryContainsKey(dns, kSCPropNetDNSServiceIdentifier)) {
+                       // if this is a service-specific resolver
                        continue;
                }
+
                if (CFSetContainsValue(seen, interface)) {
                        // if we've already processed this [scoped] interface
                        continue;
@@ -765,6 +987,14 @@ add_scoped_resolvers(CFMutableArrayRef scoped, CFDictionaryRef services, CFArray
                        flags = 0;
                }
                flags |= DNS_RESOLVER_FLAGS_SCOPED;
+
+               these_flags = 0;
+               add_dns_query_flags(serviceID, service, &these_flags);
+               if (these_flags == 0) {
+                   goto skip;
+               }
+               flags |= these_flags;
+
                num = CFNumberCreate(NULL, kCFNumberSInt32Type, &flags);
                CFDictionarySetValue(newDNS, DNS_CONFIGURATION_FLAGS_KEY, num);
                CFRelease(num);
@@ -773,7 +1003,13 @@ add_scoped_resolvers(CFMutableArrayRef scoped, CFDictionaryRef services, CFArray
                CFDictionaryRemoveValue(newDNS, kSCPropNetDNSSupplementalMatchDomains);
                CFDictionaryRemoveValue(newDNS, kSCPropNetDNSSupplementalMatchOrders);
 
+               // add the [scoped] resolver
                add_resolver(scoped, newDNS);
+
+               // add any supplemental resolver configurations for this interface
+               add_supplemental_resolvers(scoped, services, service_order, interface, service);
+
+       skip:
                CFRelease(newDNS);
        }
 
@@ -783,6 +1019,74 @@ add_scoped_resolvers(CFMutableArrayRef scoped, CFDictionaryRef services, CFArray
 }
 
 
+static void
+add_service_specific_resolvers(CFMutableArrayRef resolvers, CFDictionaryRef services)
+{
+       CFIndex services_count  = (isA_CFDictionary(services) ? CFDictionaryGetCount(services) : 0);
+
+       if (services_count > 0) {
+               CFIndex                 key_idx;
+               CFStringRef             keys_q[N_QUICK];
+               CFStringRef             *keys   = keys_q;
+               CFMutableSetRef         seen    = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
+
+               if (services_count > (CFIndex)(sizeof(keys_q) / sizeof(keys_q[0]))) {
+                       keys = CFAllocatorAllocate(kCFAllocatorDefault, services_count * sizeof(keys[0]), 0);
+               }
+
+               CFDictionaryGetKeysAndValues(services, (const void **)keys, NULL);
+
+               for (key_idx = 0; key_idx < services_count; key_idx++) {
+                       CFDictionaryRef service = CFDictionaryGetValue(services, keys[key_idx]);
+                       CFDictionaryRef dns     = CFDictionaryGetValue(service, kSCEntNetDNS);
+
+                       if (isA_CFDictionary(dns)) {
+                               CFNumberRef     service_identifier      = CFDictionaryGetValue(dns, kSCPropNetDNSServiceIdentifier);
+
+                               if (isA_CFNumber(service_identifier)) {
+                                       if (!CFSetContainsValue(seen, service_identifier)) {
+                                               CFMutableDictionaryRef  new_resolver    = CFDictionaryCreateMutableCopy(NULL, 0, dns);
+                                               CFNumberRef             flags_num;
+                                               int32_t                 flags           = 0;
+
+                                               CFSetSetValue(seen, service_identifier);
+
+                                               if (!CFDictionaryGetValueIfPresent(new_resolver, DNS_CONFIGURATION_FLAGS_KEY, (const void **)&flags_num) ||
+                                                   !isA_CFNumber(flags_num) ||
+                                                   !CFNumberGetValue(flags_num, kCFNumberSInt32Type, &flags)) {
+                                                       flags = 0;
+                                               }
+
+                                               flags |= DNS_RESOLVER_FLAGS_SERVICE_SPECIFIC | DNS_RESOLVER_FLAGS_REQUEST_ALL_RECORDS;
+
+                                               flags_num = CFNumberCreate(NULL, kCFNumberSInt32Type, &flags);
+                                               CFDictionarySetValue(new_resolver, DNS_CONFIGURATION_FLAGS_KEY, flags_num);
+                                               CFRelease(flags_num);
+
+                                               if (CFDictionaryContainsKey(new_resolver, kSCPropInterfaceName)) {
+                                                       CFDictionarySetValue(new_resolver, DNS_CONFIGURATION_SCOPED_QUERY_KEY, kCFBooleanTrue);
+                                               }
+
+                                               CFDictionaryRemoveValue(new_resolver, kSCPropNetDNSSupplementalMatchDomains);
+                                               CFDictionaryRemoveValue(new_resolver, kSCPropNetDNSSupplementalMatchOrders);
+
+                                               add_resolver(resolvers, new_resolver);
+                                               CFRelease(new_resolver);
+                                       } else {
+                                               my_log(LOG_ERR, "add_service_specific_resolvers: got a resolver with a duplicate service identifier, skipping");
+                                       }
+                               }
+                       }
+               }
+
+               if (keys != keys_q) {
+                       CFAllocatorDeallocate(kCFAllocatorDefault, keys);
+               }
+               CFRelease(seen);
+       }
+}
+
+
 static void
 add_default_resolver(CFMutableArrayRef resolvers,
                     CFDictionaryRef    defaultResolver,
@@ -801,12 +1105,13 @@ add_default_resolver(CFMutableArrayRef   resolvers,
        } else {
                myDefault = CFDictionaryCreateMutableCopy(NULL, 0, defaultResolver);
        }
+       assert(myDefault != NULL);
 
        // ensure that the default resolver has a search order
 
        order = CFDictionaryGetValue(myDefault, kSCPropNetDNSSearchOrder);
        if (!isA_CFNumber(order) ||
-           !CFNumberGetValue(order, kCFNumberIntType, &myOrder)) {
+           !CFNumberGetValue(order, kCFNumberSInt32Type, &myOrder)) {
                myOrder = DEFAULT_SEARCH_ORDER;
                order = CFNumberCreate(NULL, kCFNumberIntType, &myOrder);
                CFDictionarySetValue(myDefault, kSCPropNetDNSSearchOrder, order);
@@ -827,23 +1132,6 @@ add_default_resolver(CFMutableArrayRef    resolvers,
 }
 
 
-/*
- * rankReachability()
- *   Not reachable       == 0
- *   Connection Required == 1
- *   Reachable           == 2
- */
-static int
-rankReachability(SCNetworkReachabilityFlags flags)
-{
-       int     rank = 0;
-
-       if (flags & kSCNetworkReachabilityFlagsReachable)               rank = 2;
-       if (flags & kSCNetworkReachabilityFlagsConnectionRequired)      rank = 1;
-       return rank;
-}
-
-
 static dns_create_resolver_t
 create_resolver(CFDictionaryRef dns)
 {
@@ -851,7 +1139,6 @@ create_resolver(CFDictionaryRef dns)
        CFNumberRef             num;
        dns_create_resolver_t   _resolver;
        CFStringRef             str;
-       CFMutableArrayRef       serverAddresses         = NULL;
        CFStringRef             targetInterface         = NULL;
        unsigned int            targetInterfaceIndex    = 0;
 
@@ -906,14 +1193,23 @@ create_resolver(CFDictionaryRef dns)
                }
        }
 
+       // process flags
+       num = CFDictionaryGetValue(dns, DNS_CONFIGURATION_FLAGS_KEY);
+       if (isA_CFNumber(num)) {
+               uint32_t        flags;
+
+               if (CFNumberGetValue(num, kCFNumberSInt32Type, &flags)) {
+                       _dns_resolver_set_flags(&_resolver, flags);
+               }
+       }
+
        // process nameserver addresses
+       // Note: the flags may be overwritten if the resolver has LOOPBACK addresses
        list = CFDictionaryGetValue(dns, kSCPropNetDNSServerAddresses);
        if (isA_CFArray(list)) {
                CFIndex i;
                CFIndex n       = CFArrayGetCount(list);
 
-               serverAddresses = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-
                for (i = 0; i < n; i++) {
                        union {
                                struct sockaddr         sa;
@@ -921,7 +1217,6 @@ create_resolver(CFDictionaryRef dns)
                                struct sockaddr_in6     sin6;
                        } addr;
                        char                            buf[64];
-                       CFDataRef                       serverAddress;
 
                        str = CFArrayGetValueAtIndex(list, i);
                        if (!isA_CFString(str)) {
@@ -948,10 +1243,6 @@ create_resolver(CFDictionaryRef dns)
                        }
 
                        _dns_resolver_add_nameserver(&_resolver, &addr.sa);
-
-                       serverAddress = CFDataCreate(NULL, (const void *)&addr.sa, addr.sa.sa_len);
-                       CFArrayAppendValue(serverAddresses, serverAddress);
-                       CFRelease(serverAddress);
                }
        }
 
@@ -960,7 +1251,7 @@ create_resolver(CFDictionaryRef dns)
        if (isA_CFNumber(num)) {
                uint32_t        order;
 
-               if (CFNumberGetValue(num, kCFNumberIntType, &order)) {
+               if (CFNumberGetValue(num, kCFNumberSInt32Type, &order)) {
                        _dns_resolver_set_order(&_resolver, order);
                }
        }
@@ -1055,82 +1346,15 @@ create_resolver(CFDictionaryRef dns)
                }
        }
 
-       // process flags
-       num = CFDictionaryGetValue(dns, DNS_CONFIGURATION_FLAGS_KEY);
+       num = CFDictionaryGetValue(dns, kSCPropNetDNSServiceIdentifier);
        if (isA_CFNumber(num)) {
-               uint32_t        flags;
+               int     service_identifier;
 
-               if (CFNumberGetValue(num, kCFNumberSInt32Type, &flags)) {
-                       _dns_resolver_set_flags(&_resolver, flags);
+               if (CFNumberGetValue(num, kCFNumberIntType, &service_identifier)) {
+                       _dns_resolver_set_service_identifier(&_resolver, (uint32_t)service_identifier);
                }
        }
 
-       if (serverAddresses != NULL) {
-               SCNetworkReachabilityFlags      flags           = kSCNetworkReachabilityFlagsReachable;
-               CFIndex                         i;
-               CFIndex                         n               = CFArrayGetCount(serverAddresses);
-               CFMutableDictionaryRef          targetOptions;
-
-               targetOptions = CFDictionaryCreateMutable(NULL,
-                                                         0,
-                                                         &kCFTypeDictionaryKeyCallBacks,
-                                                         &kCFTypeDictionaryValueCallBacks);
-               CFDictionarySetValue(targetOptions,
-                                    kSCNetworkReachabilityOptionServerBypass,
-                                    kCFBooleanTrue);
-               if (targetInterface != NULL) {
-                       CFDictionarySetValue(targetOptions,
-                                            kSCNetworkReachabilityOptionInterface,
-                                            targetInterface);
-               }
-
-               for (i = 0; i < n; i++) {
-                       SCNetworkReachabilityFlags      ns_flags;
-                       Boolean                         ok;
-                       CFDataRef                       serverAddress;
-                       SCNetworkReachabilityRef        target;
-
-                       serverAddress = CFArrayGetValueAtIndex(serverAddresses, i);
-                       CFDictionarySetValue(targetOptions,
-                                            kSCNetworkReachabilityOptionRemoteAddress,
-                                            serverAddress);
-                       target = SCNetworkReachabilityCreateWithOptions(NULL, targetOptions);
-                       if (target == NULL) {
-                               CFDictionaryRemoveValue(targetOptions, kSCNetworkReachabilityOptionInterface);
-                               target = SCNetworkReachabilityCreateWithOptions(NULL, targetOptions);
-                               if (target != NULL) {
-                                       // if interface name not (no longer) valid
-                                       CFRelease(target);
-                                       flags = 0;
-                                       break;
-                               }
-
-                               // address not valid?
-                               SCLog(TRUE, LOG_ERR,
-                                     CFSTR("create_resolver SCNetworkReachabilityCreateWithOptions() failed:\n  options = %@"),
-                                     targetOptions);
-                               break;
-                       }
-
-                       ok = SCNetworkReachabilityGetFlags(target, &ns_flags);
-                       CFRelease(target);
-                       if (!ok) {
-                               break;
-                       }
-
-                       if ((i == 0) ||
-                           (rankReachability(ns_flags) < rankReachability(flags))) {
-                               /* return the worst case result */
-                               flags = ns_flags;
-                       }
-               }
-
-               _dns_resolver_set_reach_flags(&_resolver, flags);
-
-               CFRelease(targetOptions);
-               CFRelease(serverAddresses);
-       }
-
        if (targetInterface != NULL) {
                CFRelease(targetInterface);
        }
@@ -1157,6 +1381,25 @@ isScopedConfiguration(CFDictionaryRef dns)
 }
 
 
+static __inline__ Boolean
+isServiceSpecificConfiguration(CFDictionaryRef dns)
+{
+       uint32_t        flags;
+       CFNumberRef     num;
+
+       if (dns != NULL &&
+           CFDictionaryGetValueIfPresent(dns, DNS_CONFIGURATION_FLAGS_KEY, (const void **)&num) &&
+           num != NULL &&
+           CFNumberGetValue(num, kCFNumberSInt32Type, &flags) &&
+           (flags & DNS_RESOLVER_FLAGS_SERVICE_SPECIFIC))
+       {
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+
 static CFComparisonResult
 compareDomain(const void *val1, const void *val2, void *context)
 {
@@ -1256,11 +1499,12 @@ dns_configuration_set(CFDictionaryRef   defaultResolver,
                      CFArrayRef        privateResolvers)
 {
        dns_create_config_t     _config;
-       Boolean                 changed         = FALSE;
+       Boolean                 changed                 = FALSE;
+       uint32_t                dns_resolver_flags      = 0;
        CFIndex                 i;
        CFMutableDictionaryRef  myDefault;
-       Boolean                 myOrderAdded    = FALSE;
-       CFArrayRef              mySearchDomains = NULL;
+       Boolean                 myOrderAdded            = FALSE;
+       CFArrayRef              mySearchDomains         = NULL;
        CFIndex                 n_resolvers;
        CFMutableArrayRef       resolvers;
        unsigned char           signature[CC_SHA1_DIGEST_LENGTH];
@@ -1269,10 +1513,11 @@ dns_configuration_set(CFDictionaryRef   defaultResolver,
        // establish list of resolvers
 
        resolvers = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+       assert(resolvers != NULL);
 
        // collect (and add) any "supplemental" resolver configurations
 
-       add_supplemental_resolvers(resolvers, services, serviceOrder);
+       add_supplemental_resolvers(resolvers, services, serviceOrder, NULL, NULL);
 
        // collect (and add) any "private" resolver configurations
 
@@ -1290,6 +1535,10 @@ dns_configuration_set(CFDictionaryRef   defaultResolver,
 
        add_scoped_resolvers(resolvers, services, serviceOrder);
 
+       // collect (and add) any "service-specific" resolver configurations
+
+       add_service_specific_resolvers(resolvers, services);
+
        // sort resolvers
 
        n_resolvers = CFArrayGetCount(resolvers);
@@ -1349,36 +1598,80 @@ dns_configuration_set(CFDictionaryRef   defaultResolver,
                 */
                _config = _dns_configuration_create();
 
-               // add resolvers
+               CFDictionaryApplyFunction(services, add_dns_query_flags , &dns_resolver_flags);
 
                for (i = 0; i < n_resolvers; i++) {
+                       boolean_t               is_default_resolver;
                        CFDictionaryRef         resolver;
                        dns_create_resolver_t   _resolver;
 
                        resolver = CFArrayGetValueAtIndex(resolvers, i);
+
+                       is_default_resolver = (!isScopedConfiguration(resolver) && !isServiceSpecificConfiguration(resolver));
+                       if (is_default_resolver) {
+                               CFMutableDictionaryRef  new_resolver;
+                               CFNumberRef             num;
+
+                               new_resolver = CFDictionaryCreateMutableCopy(NULL, 0, resolver);
+
+                               num = CFNumberCreate(NULL, kCFNumberSInt32Type, &dns_resolver_flags);
+                               CFDictionarySetValue(new_resolver, DNS_CONFIGURATION_FLAGS_KEY, num);
+                               CFRelease(num);
+
+                               resolver = new_resolver;
+                       }
+
                        _resolver = create_resolver(resolver);
                        _dns_configuration_add_resolver(&_config, _resolver);
                        _dns_resolver_free(&_resolver);
+
+                       if (is_default_resolver) {
+                               CFRelease(resolver);
+                       }
                }
 
 #if    !TARGET_OS_IPHONE
                // add flatfile resolvers
 
+               _dnsinfo_flatfile_set_flags(dns_resolver_flags);
                _dnsinfo_flatfile_add_resolvers(&_config);
 #endif // !TARGET_OS_IPHONE
        }
 
+#ifdef DNS_CONFIGURATION_DEBUG
+       {
+               uint8_t                 *buf;
+               dns_config_t            *config;
+               _dns_config_buf_t       *config_buf;
+               uint32_t                n_config;
+               uint32_t                n_padding;
+
+               config_buf = (_dns_config_buf_t *)_config;
+               n_config  = sizeof(_dns_config_buf_t) + ntohl(config_buf->n_attribute);
+               n_padding = ntohl(config_buf->n_padding);
+               buf = malloc(n_config + n_padding);
+               bcopy((void *)config_buf, buf, n_config);
+               bzero(&buf[n_config], n_padding);
+               config = expand_config((_dns_config_buf_t *)buf);
+               _dns_configuration_print(config);
+               free(buf);
+       }
+#endif // DNS_CONFIGURATION_DEBUG
+
        // check if the configuration changed
        _dns_configuration_signature(&_config, signature, sizeof(signature));
        if (bcmp(signature, signature_last, sizeof(signature)) != 0) {
+               // save [new] signature
+               bcopy(signature, signature_last, sizeof(signature));
+
+               // save [new] configuration
+               if (!_dns_configuration_store(&_config)) {
+                       my_log(LOG_ERR, "dns_configuration_set: could not store configuration");
+               }
+
                changed = TRUE;
        }
-       bcopy(signature, signature_last, sizeof(signature));
 
-       // save configuration
-       if (!_dns_configuration_store(&_config)) {
-               SCLog(TRUE, LOG_ERR, CFSTR("dns_configuration_set: could not store configuration"));
-       }
        if (_config != NULL) _dns_configuration_free(&_config);
 
        CFRelease(resolvers);
@@ -1408,7 +1701,7 @@ dns_configuration_changed(CFMachPortRef port, void *msg, CFIndex size, void *inf
        }
        resolvers_save = resolvers_now;
 
-       SCLog(TRUE, LOG_DEBUG, CFSTR(_PATH_RESOLVER_DIR " changed"));
+       my_log(LOG_DEBUG, _PATH_RESOLVER_DIR " changed");
 
        // fake a "DNS" change
        keys = CFArrayCreate(NULL, (const void **)&key, 1, &kCFTypeArrayCallBacks);
@@ -1433,13 +1726,13 @@ dns_configuration_monitor(SCDynamicStoreRef store, SCDynamicStoreCallBack callou
 
        status = notify_register_mach_port(_PATH_RESOLVER_DIR, &notify_port, 0, &notify_token);
        if (status != NOTIFY_STATUS_OK) {
-               SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("notify_register_mach_port() failed"));
+               my_log(LOG_ERR, "notify_register_mach_port() failed");
                return;
        }
 
        status = notify_monitor_file(notify_token, "/private" _PATH_RESOLVER_DIR, 0);
        if (status != NOTIFY_STATUS_OK) {
-               SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("notify_monitor_file() failed"));
+               my_log(LOG_ERR, "notify_monitor_file() failed");
                (void)notify_cancel(notify_token);
                return;
        }
@@ -1451,7 +1744,7 @@ dns_configuration_monitor(SCDynamicStoreRef store, SCDynamicStoreCallBack callou
 
        rls = CFMachPortCreateRunLoopSource(NULL, mp, -1);
        if (rls == NULL) {
-               SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("SCDynamicStoreCreateRunLoopSource() failed"));
+               my_log(LOG_ERR, "SCDynamicStoreCreateRunLoopSource() failed");
                CFRelease(mp);
                (void)notify_cancel(notify_token);
                return;
@@ -1513,7 +1806,21 @@ split(const void * key, const void * value, void * context)
 
        if (CFEqual(entity_id, kSCEntNetIPv4) ||
            CFEqual(entity_id, kSCEntNetIPv6)) {
-               CFStringRef     interface;
+               CFStringRef             interface;
+
+               if (CFEqual(entity_id, kSCEntNetIPv4)) {
+                       CFMutableDictionaryRef  ipv4_dict;
+
+                       ipv4_dict = CFDictionaryCreateMutable(NULL,
+                                                             0,
+                                                             &kCFTypeDictionaryKeyCallBacks,
+                                                             &kCFTypeDictionaryValueCallBacks);
+                       CFDictionarySetValue(ipv4_dict, kIPv4DictService, (CFDictionaryRef)value);
+                       CFDictionarySetValue(state_dict, entity_id, ipv4_dict);
+                       CFRelease(ipv4_dict);
+               } else {
+                       CFDictionarySetValue(state_dict, entity_id, (CFDictionaryRef)value);
+               }
 
                interface = CFDictionaryGetValue((CFDictionaryRef)value, kSCPropInterfaceName);
                if (interface != NULL) {
@@ -1525,9 +1832,9 @@ split(const void * key, const void * value, void * context)
                                new_dns = CFDictionaryCreateMutableCopy(NULL, 0, dns);
                        } else {
                                new_dns = CFDictionaryCreateMutable(NULL,
-                                                               0,
-                                                               &kCFTypeDictionaryKeyCallBacks,
-                                                               &kCFTypeDictionaryValueCallBacks);
+                                                                   0,
+                                                                   &kCFTypeDictionaryKeyCallBacks,
+                                                                   &kCFTypeDictionaryValueCallBacks);
                        }
                        CFDictionarySetValue(new_dns, kSCPropInterfaceName, interface);
                        CFDictionarySetValue(state_dict, kSCEntNetDNS, new_dns);
index 08dc9e10f171ea55fbcdf458d11f90ce4ee2882c..b218d3a4f5b4e3f2e839d9504ad4dfb0488a178d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2008, 2009, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2006, 2008, 2009, 2011, 2012 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 
 __BEGIN_DECLS
 
-__private_extern__
 void   dns_configuration_init          (CFBundleRef            bundle);
 
 
 #if    !TARGET_OS_IPHONE
-__private_extern__
 void   dns_configuration_monitor       (SCDynamicStoreRef      store,
                                         SCDynamicStoreCallBack callout);
 #endif // !TARGET_OS_IPHONE
 
-__private_extern__
 Boolean        dns_configuration_set           (CFDictionaryRef        defaultResolver,
                                         CFDictionaryRef        services,
                                         CFArrayRef             serviceOrder,
index cb683f422b4179feee7cde7d3066973557e9d9d6..328ceb98a81f35feee4f7dc5f7a1e4d2cdf38947 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2012 Apple Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2013 Apple Inc.  All Rights Reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #include <limits.h>
 #include <notify.h>
 #include <mach/mach_time.h>
+#include <dispatch/dispatch.h>
+#include <CommonCrypto/CommonDigest.h>
 
 #include <SystemConfiguration/SystemConfiguration.h>
 #include <SystemConfiguration/SCDynamicStoreCopyDHCPInfo.h>
 #include <SystemConfiguration/SCValidation.h>
+#include <SystemConfiguration/scprefs_observer.h>
 #include <SystemConfiguration/SCPrivate.h>     /* for SCLog() */
+#include "SCNetworkReachabilityInternal.h"
+#include "SCNetworkSignaturePrivate.h"
 #include <dnsinfo.h>
-#if    !TARGET_OS_IPHONE
-#include <dnsinfo_create.h>
-#endif /* !TARGET_OS_IPHONE */
+#include "dnsinfo_server.h"
+
+#if    defined(HAVE_IPSEC_STATUS) || defined(HAVE_VPN_STATUS)
+#include <ppp/PPPControllerPriv.h>
+#endif // !defined(HAVE_IPSEC_STATUS) || defined(HAVE_VPN_STATUS)
 
 #include <dns_sd.h>
 #ifndef        kDNSServiceCompMulticastDNS
 #endif
 #include <network_information.h>
 #include "network_information_priv.h"
+#include "network_information_server.h"
+#include <ppp/ppp_msg.h>
 
 enum {
     kProtocolFlagsNone         = 0x0,
@@ -130,19 +139,43 @@ enum {
 #define ROUTELIST_DEBUG(a, f)
 #endif
 
+#if    !TARGET_IPHONE_SIMULATOR
 #include "set-hostname.h"
+#endif /* !TARGET_IPHONE_SIMULATOR */
+
 #include "dns-configuration.h"
 #include "proxy-configuration.h"
+
 #if    !TARGET_OS_IPHONE
 #include "smb-configuration.h"
 #endif /* !TARGET_OS_IPHONE */
 
+/*
+ * Property: kIPIsCoupled
+ * Purpose:
+ *   Used to indicate that the IPv4 and IPv6 services are coupled.
+ *   Neither the IPv4 part nor the IPv6 part of a coupled service
+ *   may become primary if IPv4 or IPv6 is primary for another interface.
+ *
+ *   For example, if the service over en3 is "coupled" and has IPv6,
+ *   and en0 is primary for just IPv4, IPv6 over en3 is not eligible
+ *   to become primary for IPv6.
+ */
+#define kIPIsCoupled   CFSTR("IPIsCoupled")
+
 #define PPP_PREFIX     "ppp"
 
 #define IP_FORMAT      "%d.%d.%d.%d"
 #define IP_CH(ip)      ((u_char *)(ip))
 #define IP_LIST(ip)    IP_CH(ip)[0],IP_CH(ip)[1],IP_CH(ip)[2],IP_CH(ip)[3]
 
+#include "ip_plugin.h"
+#if    ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 60000))
+static SCLoggerRef     S_IPMonitor_logger;
+#endif // ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 60000))
+
+static boolean_t       S_bundle_logging_verbose;
+
 /*
  * IPv4 Route management
  */
@@ -153,6 +186,7 @@ enum {
     kRouteIsDirectToInterfaceFlag      = 0x00000001,
     kRouteIsNotSubnetLocalFlag         = 0x00000002,
     kRouteIsScopedFlag                 = 0x00000004,
+    kRouteIsNULLFlag                   = 0x00000008
 };
 
 typedef struct {
@@ -169,6 +203,7 @@ typedef struct {
 typedef struct {
     int                        count;
     int                        size;
+    boolean_t          exclude_from_nwi;
     IPv4Route          list[1];        /* variable length */
 } IPv4RouteList, *IPv4RouteListRef;
 
@@ -177,27 +212,49 @@ enum {
     kIPv4RouteListRemoveRouteCommand
 };
 
-typedef struct {
-    char               ifname[IFNAMSIZ];
-    uint32_t           flags;
-    Rank               rank;
-    struct in6_addr    iaddr6;
-} IPv6RankedE, *IPv6RankedERef;
+/*
+ * Election Information
+ * - information about the current best services
+ */
+typedef struct Candidate {
+    CFStringRef                serviceID;
+    CFStringRef                if_name;
+    union {
+       struct in_addr  v4;
+       struct in6_addr v6;
+    } addr;
+    Rank                               rank;
+    boolean_t                          ip_is_coupled;
+    SCNetworkReachabilityFlags         reachability_flags;
+    union {
+       struct sockaddr_in vpn_server_addr4;
+       struct sockaddr_in6 vpn_server_addr6;
+    } vpn_server_addr;
+    CFStringRef                                signature;
+} Candidate, * CandidateRef;
 
-typedef struct {
+typedef struct ElectionResults {
     int                        count;
     int                        size;
-    IPv6RankedE                elem[1];
-} IPv6RankedList, *IPv6RankedListRef;
+    Candidate          candidates[1];
+} ElectionResults, * ElectionResultsRef;
+
+static __inline__ unsigned int
+ElectionResultsComputeSize(unsigned int n)
+{
+    return (offsetof(ElectionResults, candidates[n]));
+}
 
 /*
  * Type: Rank
  * Purpose:
  *   A 32-bit value to encode the relative rank of a service.
  *
- *   The top 8 bits are used to hold the rank assertion (first, last, never, default),
- *   the bottom 24 bits are used to store the service index i.e. the position within
- *   the service order array.
+ *   The top 8 bits are used to hold the rank assertion (first, last
+ *   never, default).
+ *
+ *   The bottom 24 bits are used to store the service index (i.e. the
+ *   position within the service order array).
  */
 #define RANK_ASSERTION_MAKE(r)         ((Rank)(r) << 24)
 #define kRankAssertionFirst            RANK_ASSERTION_MAKE(0)
@@ -241,6 +298,7 @@ static SCDynamicStoreRef    S_session = NULL;
 
 /* debug output flags */
 static uint32_t                        S_IPMonitor_debug = 0;
+static Boolean                 S_IPMonitor_verbose = FALSE;
 
 /* are we netbooted?  If so, don't touch the default route */
 static boolean_t               S_netboot = FALSE;
@@ -268,6 +326,10 @@ static CFStringRef         S_primary_ipv6 = NULL;
 static CFStringRef             S_primary_dns = NULL;
 static CFStringRef             S_primary_proxies = NULL;
 
+/* the current election results */
+static ElectionResultsRef      S_ipv4_results;
+static ElectionResultsRef      S_ipv6_results;
+
 static CFStringRef             S_state_global_ipv4 = NULL;
 static CFStringRef             S_state_global_ipv6 = NULL;
 static CFStringRef             S_state_global_dns = NULL;
@@ -279,18 +341,40 @@ static CFStringRef                S_setup_service_prefix = NULL;
 static CFStringRef             S_multicast_resolvers = NULL;
 static CFStringRef             S_private_resolvers = NULL;
 
+#if    !TARGET_IPHONE_SIMULATOR
 static IPv4RouteListRef                S_ipv4_routelist = NULL;
+#endif /* !TARGET_IPHONE_SIMULATOR */
 
 static const struct in_addr    S_ip_zeros = { 0 };
 static const struct in6_addr   S_ip6_zeros = IN6ADDR_ANY_INIT;
 
 static boolean_t               S_append_state = FALSE;
 
+static CFDictionaryRef         S_dns_dict = NULL;
+
+static Boolean                 S_dnsinfo_synced = TRUE;
+
 static nwi_state_t             S_nwi_state = NULL;
+static Boolean                 S_nwi_synced = TRUE;
+
+static CFDictionaryRef         S_proxies_dict = NULL;
+
+// Note: access should be gated with __network_change_queue()
+static uint32_t                        S_network_change_needed = 0;
+#define        NETWORK_CHANGE_NET      1<<0
+#define        NETWORK_CHANGE_DNS      1<<1
+#define        NETWORK_CHANGE_PROXY    1<<2
+#if    !TARGET_OS_IPHONE
+#define        NETWORK_CHANGE_SMB      1<<3
+#endif /* !TARGET_OS_IPHONE */
+static struct timeval          S_network_change_start;
+static Boolean                 S_network_change_timeout = FALSE;
+static dispatch_source_t       S_network_change_timer = NULL;
 
 #if    !TARGET_OS_IPHONE
 static CFStringRef             S_primary_smb = NULL;
 static CFStringRef             S_state_global_smb = NULL;
+static CFDictionaryRef         S_smb_dict = NULL;
 #endif /* !TARGET_OS_IPHONE */
 
 #if    !TARGET_OS_IPHONE
@@ -314,6 +398,7 @@ enum {
     kEntityTypeSMB,
 #endif /* !TARGET_OS_IPHONE */
     ENTITY_TYPES_COUNT,
+    kEntityTypeVPNStatus,
     kEntityTypeServiceOptions  = 31
 };
 typedef uint32_t       EntityType;
@@ -328,13 +413,20 @@ static const CFStringRef *entityTypeNames[ENTITY_TYPES_COUNT] = {
 #endif /* !TARGET_OS_IPHONE */
 };
 
-#ifndef kSCEntNetIPv4RouteList
-#define kSCEntNetIPv4RouteList CFSTR("IPv4RouteList")
-#endif
+static Boolean
+S_dict_get_boolean(CFDictionaryRef dict, CFStringRef key, Boolean def_value);
 
-#ifndef kSCEntNetIPv4ServiceDict
-#define kSCEntNetIPv4ServiceDict CFSTR("IPv4ServiceDict")
-#endif
+static __inline__ char
+ipvx_char(int af)
+{
+    return ((af == AF_INET) ? '4' : '6');
+}
+
+static __inline__ char
+ipvx_other_char(int af)
+{
+    return ((af == AF_INET) ? '6' : '4');
+}
 
 static IPv4RouteListRef
 ipv4_dict_get_routelist(CFDictionaryRef ipv4_dict)
@@ -346,7 +438,7 @@ ipv4_dict_get_routelist(CFDictionaryRef ipv4_dict)
        return (NULL);
     }
 
-    routes = CFDictionaryGetValue(ipv4_dict, kSCEntNetIPv4RouteList);
+    routes = CFDictionaryGetValue(ipv4_dict, kIPv4DictRoutes);
 
     if (routes != NULL) {
        routes_list = (IPv4RouteListRef)(void*)CFDataGetBytePtr(routes);
@@ -364,7 +456,7 @@ ipv4_dict_get_ifname(CFDictionaryRef ipv4_dict)
     }
 
     ipv4_service_dict = CFDictionaryGetValue(ipv4_dict,
-                                            kSCEntNetIPv4ServiceDict);
+                                            kIPv4DictService);
 
     if (isA_CFDictionary(ipv4_service_dict) == NULL) {
        return NULL;
@@ -458,6 +550,14 @@ keyChangeListFree(keyChangeListRef keys)
     return;
 }
 
+static Boolean
+keyChangeListActive(keyChangeListRef keys)
+{
+    return ((CFDictionaryGetCount(keys->set) > 0) ||
+           (CFArrayGetCount(keys->remove) > 0) ||
+           (CFArrayGetCount(keys->notify) > 0));
+}
+
 static void
 keyChangeListNotifyKey(keyChangeListRef keys, CFStringRef key)
 {
@@ -482,13 +582,11 @@ keyChangeListSetValue(keyChangeListRef keys, CFStringRef key, CFTypeRef value)
 }
 
 static void
-keyChangeListApplyToStore(keyChangeListRef keys, SCDynamicStoreRef session,
-                         CFStringRef network_change_msg)
+keyChangeListApplyToStore(keyChangeListRef keys, SCDynamicStoreRef session)
 {
     CFArrayRef         notify = keys->notify;
     CFArrayRef         remove = keys->remove;
     CFDictionaryRef    set = keys->set;
-    int                        status;
 
     if (CFArrayGetCount(notify) == 0) {
        notify = NULL;
@@ -504,32 +602,87 @@ keyChangeListApplyToStore(keyChangeListRef keys, SCDynamicStoreRef session,
     }
     if (S_IPMonitor_debug & kDebugFlag1) {
        if (set != NULL) {
-           SCLog(TRUE, LOG_NOTICE, CFSTR("IPMonitor: Setting:\n%@"),
-                 set);
+           my_log(LOG_DEBUG, "IPMonitor: Setting:\n%@", set);
        }
        if (remove != NULL) {
-           SCLog(TRUE, LOG_NOTICE, CFSTR("IPMonitor: Removing:\n%@"),
-                 remove);
+           my_log(LOG_DEBUG, "IPMonitor: Removing:\n%@", remove);
        }
        if (notify != NULL) {
-           SCLog(TRUE, LOG_NOTICE, CFSTR("IPMonitor: Notifying:\n%@"),
-                 notify);
+           my_log(LOG_DEBUG, "IPMonitor: Notifying:\n%@", notify);
        }
     }
     (void)SCDynamicStoreSetMultiple(session, set, remove, notify);
 
-    status = notify_post("com.apple.system.config.network_change");
-    if (status == NOTIFY_STATUS_OK) {
-       if (CFStringGetLength(network_change_msg) != 0) {
-           SCLog(TRUE, LOG_NOTICE, CFSTR("network changed:%@"), network_change_msg);
-       } else {
-           SCLog(TRUE, LOG_NOTICE, CFSTR("network changed."));
+    return;
+}
+
+static void
+S_nwi_ifstate_dump(nwi_ifstate_t ifstate, int i)
+{
+    const char *               addr_str;
+    void *                     address;
+    char                       ntopbuf[INET6_ADDRSTRLEN];
+    char                       vpn_ntopbuf[INET6_ADDRSTRLEN];
+    const struct sockaddr *    vpn_addr;
+
+    address = nwi_ifstate_get_address(ifstate);
+    addr_str = inet_ntop(ifstate->af, address, ntopbuf, sizeof(ntopbuf));
+    vpn_addr = nwi_ifstate_get_vpn_server(ifstate);
+    if (vpn_addr != NULL) {
+       _SC_sockaddr_to_string(nwi_ifstate_get_vpn_server(ifstate),
+                              vpn_ntopbuf,
+                              sizeof(vpn_ntopbuf));
+    }
+    my_log(LOG_DEBUG,
+          "    [%d]: %s%s%s%s rank 0x%x iaddr: %s%s%s reachability_flags %u",
+          i, ifstate->ifname,
+          ifstate->diff_str != NULL ? ifstate->diff_str : "",
+          (ifstate->flags & NWI_IFSTATE_FLAGS_HAS_DNS) != 0
+          ? " dns" : "",
+          (ifstate->flags & NWI_IFSTATE_FLAGS_NOT_IN_LIST) != 0
+          ? " never" : "",
+          ifstate->rank,
+          addr_str,
+          (vpn_addr != NULL) ? " vpn_server_addr: " : "",
+          (vpn_addr != NULL) ? vpn_ntopbuf : "",
+          ifstate->reach_flags);
+    return;
+}
+
+static void
+S_nwi_state_dump(nwi_state_t state)
+{
+    int                        i;
+    nwi_ifstate_t      scan;
+
+    if (state == NULL) {
+       my_log(LOG_DEBUG, "nwi_state = <none>");
+       return;
+    }
+    my_log(LOG_DEBUG,
+          "nwi_state = { "
+          "gen = %llu size = %u #ipv4 = %u #ipv6 = %u "
+          "reach_flags_v4 = %u reach_flags_v6 %u }",
+          state->generation_count,
+          state->size,
+          state->ipv4_count,
+          state->ipv6_count,
+          nwi_state_get_reachability_flags(state, AF_INET),
+          nwi_state_get_reachability_flags(state, AF_INET6));
+    if (state->ipv4_count) {
+       my_log(LOG_DEBUG, "IPv4:");
+       for (i = 0, scan = state->nwi_ifstates;
+            i < state->ipv4_count; i++, scan++) {
+           S_nwi_ifstate_dump(scan, i);
+       }
+    }
+    if (state->ipv6_count) {
+       my_log(LOG_DEBUG, "IPv6:");
+       for (i = 0, scan = state->nwi_ifstates + state->ipv6_start;
+            i < state->ipv6_count; i++, scan++) {
+           S_nwi_ifstate_dump(scan, i);
        }
-    } else {
-       SCLog(TRUE, LOG_NOTICE,
-             CFSTR("IPMonitor: notify_post() failed: error=%ld"), status);
     }
-
     return;
 }
 
@@ -547,6 +700,7 @@ S_is_network_boot()
     return (netboot);
 }
 
+#if    !TARGET_IPHONE_SIMULATOR
 static __inline__ int
 inet6_dgram_socket()
 {
@@ -585,6 +739,7 @@ siocdrdel_in6(int s, int if_index, const struct in6_addr * addr)
     return (ioctl(s, SIOCDRDEL_IN6, &dr));
 }
 #endif /* SIOCDRADD_IN6 */
+#endif /* !TARGET_IPHONE_SIMULATOR */
 
 #ifdef RTF_IFSCOPE
 static boolean_t
@@ -597,7 +752,7 @@ S_is_scoped_routing_enabled()
                      &scopedroute, &len,
                      NULL, 0) == -1)
        && (errno != ENOENT)) {
-       SCLog(TRUE, LOG_ERR, CFSTR("sysctlbyname() failed: %s"), strerror(errno));
+       my_log(LOG_ERR, "sysctlbyname() failed: %s", strerror(errno));
     }
     return (scopedroute);
 }
@@ -612,7 +767,7 @@ S_is_scoped_v6_routing_enabled()
                      &scopedroute_v6, &len,
                      NULL, 0) == -1)
        && (errno != ENOENT)) {
-       SCLog(TRUE, LOG_ERR, CFSTR("sysctlbyname() failed: %s"), strerror(errno));
+       my_log(LOG_ERR, "sysctlbyname() failed: %s", strerror(errno));
     }
     return (scopedroute_v6);
 }
@@ -706,13 +861,15 @@ cfstring_to_ipvx(int family, CFStringRef str, void * addr, int addr_size)
     return (FALSE);
 }
 
-static boolean_t
+__private_extern__
+boolean_t
 cfstring_to_ip(CFStringRef str, struct in_addr * ip_p)
 {
     return (cfstring_to_ipvx(AF_INET, str, ip_p, sizeof(*ip_p)));
 }
 
-static boolean_t
+__private_extern__
+boolean_t
 cfstring_to_ip6(CFStringRef str, struct in6_addr * ip6_p)
 {
     return (cfstring_to_ipvx(AF_INET6, str, ip6_p, sizeof(*ip6_p)));
@@ -838,14 +995,17 @@ IPv4RouteCopyDescriptionWithString(IPv4RouteRef r, CFMutableStringRef str)
                         IP_LIST(&r->gateway),
                         (r->ifname[0] != '\0') ? r->ifname : "<none>",
                         IP_LIST(&r->ifa));
-    if ((r->flags & kRouteIsNotSubnetLocalFlag) != 0) {
-       CFStringAppend(str, CFSTR(" [non-local]"));
-    }
-    else if ((r->flags & kRouteIsDirectToInterfaceFlag) != 0) {
-       CFStringAppend(str, CFSTR(" [direct]"));
+    if ((r->flags & kRouteIsNULLFlag) != 0) {
+       CFStringAppend(str, CFSTR(" [null]"));
     }
-
-    switch(rank_assertion) {
+    else {
+       if ((r->flags & kRouteIsNotSubnetLocalFlag) != 0) {
+           CFStringAppend(str, CFSTR(" [non-local]"));
+       }
+       else if ((r->flags & kRouteIsDirectToInterfaceFlag) != 0) {
+           CFStringAppend(str, CFSTR(" [direct]"));
+       }
+       switch (rank_assertion) {
        case kRankAssertionFirst:
            CFStringAppend(str, CFSTR(" [first]"));
            break;
@@ -857,10 +1017,10 @@ IPv4RouteCopyDescriptionWithString(IPv4RouteRef r, CFMutableStringRef str)
            break;
        default:
            break;
-    }
-
-    if ((r->flags & kRouteIsScopedFlag) != 0) {
-       CFStringAppend(str, CFSTR(" [SCOPED]"));
+       }
+       if ((r->flags & kRouteIsScopedFlag) != 0) {
+           CFStringAppend(str, CFSTR(" [SCOPED]"));
+       }
     }
     return;
 }
@@ -886,11 +1046,11 @@ IPv4RoutePrint(IPv4RouteRef route)
 }
 
 static __inline__ void
-IPv4RouteLog(IPv4RouteRef route)
+IPv4RouteLog(int level, IPv4RouteRef route)
 {
     CFStringRef        str = IPv4RouteCopyDescription(route);
 
-    SCLog(TRUE, LOG_NOTICE, CFSTR("%@"), str);
+    my_log(level, "%@", str);
     CFRelease(str);
     return;
 }
@@ -936,8 +1096,8 @@ IPv4RouteCompare(IPv4RouteRef a, Rank a_rank,
        }
        a_str = IPv4RouteCopyDescription(a);
        b_str = IPv4RouteCopyDescription(b);
-       SCLog(TRUE, LOG_NOTICE, CFSTR("%@ rank %u %c %@ rank %u"),
-             a_str, a_rank, ch, b_str, b_rank);
+       my_log(LOG_DEBUG, "%@ rank 0x%x %c %@ rank 0x%x",
+              a_str, a_rank, ch, b_str, b_rank);
        CFRelease(a_str);
        CFRelease(b_str);
     }
@@ -973,11 +1133,11 @@ IPv4RouteListPrint(IPv4RouteListRef routes)
 }
 
 static __inline__ void
-IPv4RouteListLog(IPv4RouteListRef routes)
+IPv4RouteListLog(int level, IPv4RouteListRef routes)
 {
     CFStringRef        str = IPv4RouteListCopyDescription(routes);
 
-    SCLog(TRUE, LOG_NOTICE, CFSTR("%@"), str);
+    my_log(level, "%@", str);
     CFRelease(str);
     return;
 }
@@ -988,6 +1148,7 @@ IPv4RouteListComputeSize(unsigned int n)
     return (offsetof(IPv4RouteList, list[n]));
 }
 
+#if    !TARGET_IPHONE_SIMULATOR
 static IPv4RouteRef
 IPv4RouteListFindRoute(IPv4RouteListRef routes, IPv4RouteRef route)
 {
@@ -1054,6 +1215,7 @@ IPv4RouteListApply(IPv4RouteListRef old_routes, IPv4RouteListRef new_routes,
     }
     return;
 }
+#endif /* !TARGET_IPHONE_SIMULATOR */
 
 /*
  * Function: IPv4RouteListAddRoute
@@ -1088,6 +1250,7 @@ IPv4RouteListAddRoute(IPv4RouteListRef routes, int init_size,
 
     if (routes == NULL) {
        routes = (IPv4RouteListRef)malloc(IPv4RouteListComputeSize(init_size));
+       bzero(routes, sizeof(*routes));
        routes->size = init_size;
        routes->count = 0;
     }
@@ -1144,7 +1307,8 @@ IPv4RouteListAddRoute(IPv4RouteListRef routes, int init_size,
                if (scan->flags & kRouteIsScopedFlag) {
                    is_scoped = TRUE;
                }
-               ROUTELIST_DEBUG(("Hit 4:replacing [%d] rank %u < %u\n", i,
+               ROUTELIST_DEBUG(("Hit 4:replacing [%d] rank 0x%x < 0x%x\n",
+                                i,
                                 this_rank,
                                 scan->rank), kDebugFlag8);
                *scan = *this_route;
@@ -1208,6 +1372,9 @@ IPv4RouteListAddRoute(IPv4RouteListRef routes, int init_size,
     /* copy the route */
     routes->list[where] = *this_route;
     routes->list[where].rank = this_rank;
+    if (RANK_ASSERTION_MASK(this_rank) == kRankAssertionNever) {
+       routes->list[where].flags |= kRouteIsScopedFlag;
+    }
 
     /* set the scope */
     switch (scope_which) {
@@ -1284,6 +1451,7 @@ IPv4RouteListCreateWithDictionary(IPv4RouteListRef routes,
                                  CFStringRef primaryRank)
 {
     struct in_addr     addr = { 0 };
+    boolean_t          exclude_from_nwi = FALSE;
     RouteFlags         flags = 0;
     unsigned int       ifindex;
     char               ifn[IFNAMSIZ];
@@ -1324,6 +1492,8 @@ IPv4RouteListCreateWithDictionary(IPv4RouteListRef routes,
        if (ntohl(subnet.s_addr) != IN_LINKLOCALNETNUM) {
            add_subnet = TRUE;
            n++;
+       } else if (router.s_addr == 0) {
+           exclude_from_nwi = TRUE;
        }
     }
     if (addr.s_addr == 0) {
@@ -1331,8 +1501,19 @@ IPv4RouteListCreateWithDictionary(IPv4RouteListRef routes,
        return (NULL);
     }
     if (router.s_addr == 0) {
+       /*
+        * If no router is configured, demote the rank. If there's already
+        * a rank assertion that indicates RankNever, use that, otherwise
+        * use RankLast.
+        */
        flags |= kRouteIsDirectToInterfaceFlag;
-       rank = kRankAssertionLast;
+       if (primaryRank != NULL
+           && PrimaryRankGetRankAssertion(primaryRank) == kRankAssertionNever) {
+           rank = kRankAssertionNever;
+       }
+       else {
+           rank = kRankAssertionLast;
+       }
     }
     else {
        /*
@@ -1350,6 +1531,11 @@ IPv4RouteListCreateWithDictionary(IPv4RouteListRef routes,
        }
     }
 
+    if (S_dict_get_boolean(dict, kIsNULL, FALSE)) {
+       exclude_from_nwi = TRUE;
+       flags |= kRouteIsNULLFlag;
+    }
+
     if (rank == kRankAssertionNever) {
        flags |= kRouteIsScopedFlag;
     }
@@ -1370,6 +1556,7 @@ IPv4RouteListCreateWithDictionary(IPv4RouteListRef routes,
     }
     bzero(routes, IPv4RouteListComputeSize(n));
     routes->count = n;
+    routes->exclude_from_nwi = exclude_from_nwi;
 
     /* start at the beginning */
     r = routes->list;
@@ -1387,14 +1574,14 @@ IPv4RouteListCreateWithDictionary(IPv4RouteListRef routes,
            r->gateway = addr;
        }
        r->rank = rank;
-       if (r->rank == kRankAssertionNever) {
-           r->flags |= kRouteIsScopedFlag;
-       }
        r++;
     }
 
     /* add the subnet route */
     if (add_subnet) {
+       if ((flags & kRouteIsNULLFlag) != 0) {
+           r->flags |= kRouteIsNULLFlag;
+       }
        r->ifindex = ifindex;
        r->gateway = addr;
        r->dest = subnet;
@@ -1402,11 +1589,7 @@ IPv4RouteListCreateWithDictionary(IPv4RouteListRef routes,
        strlcpy(r->ifname, ifn, sizeof(r->ifname));
        r->ifa = addr;
        r->rank = rank;
-       if (r->rank == kRankAssertionNever) {
-           r->flags |= kRouteIsScopedFlag;
-       }
     }
-
     return (routes);
 }
 
@@ -1467,8 +1650,8 @@ service_dict_copy(CFStringRef serviceID)
 }
 
 static void
-dump_service_entity(CFStringRef serviceID, CFStringRef entity,
-                   CFStringRef operation, CFTypeRef val)
+log_service_entity(int level, CFStringRef serviceID, CFStringRef entity,
+                  CFStringRef operation, CFTypeRef val)
 {
 
     CFDataRef  route_list;
@@ -1477,14 +1660,14 @@ dump_service_entity(CFStringRef serviceID, CFStringRef entity,
     if (CFEqual(entity, kSCEntNetIPv4) && isA_CFDictionary(val) != NULL) {
        CFDictionaryRef    service_dict = NULL;
 
-       route_list = CFDictionaryGetValue(val, kSCEntNetIPv4RouteList);
+       route_list = CFDictionaryGetValue(val, kIPv4DictRoutes);
        if (route_list != NULL) {
            /* ALIGN: CF should align to at least 8-byte boundaries */
            this_val = IPv4RouteListCopyDescription((IPv4RouteListRef)
                                                    (void *)CFDataGetBytePtr(route_list));
        }
 
-       service_dict = CFDictionaryGetValue(val, kSCEntNetIPv4ServiceDict);
+       service_dict = CFDictionaryGetValue(val, kIPv4DictService);
 
        if (service_dict != NULL && isA_CFDictionary(service_dict) != NULL) {
            if (this_val == NULL) {
@@ -1497,8 +1680,8 @@ dump_service_entity(CFStringRef serviceID, CFStringRef entity,
     if (val == NULL) {
        val = CFSTR("<none>");
     }
-    SCLog(TRUE, LOG_NOTICE, CFSTR("IPMonitor: serviceID %@ %@ %@ value = %@"),
-         serviceID, operation, entity, val);
+    my_log(level, "IPMonitor: serviceID %@ %@ %@ value = %@",
+          serviceID, operation, entity, val);
     my_CFRelease(&this_val);
     return;
 }
@@ -1516,8 +1699,8 @@ service_dict_set(CFStringRef serviceID, CFStringRef entity,
     if (new_val == NULL) {
        if (old_val != NULL) {
            if ((S_IPMonitor_debug & kDebugFlag1) != 0) {
-               dump_service_entity(serviceID, entity, CFSTR("Removed:"),
-                                  old_val);
+               log_service_entity(LOG_DEBUG, serviceID, entity,
+                                  CFSTR("Removed:"), old_val);
            }
            CFDictionaryRemoveValue(service_dict, entity);
            changed = TRUE;
@@ -1526,10 +1709,10 @@ service_dict_set(CFStringRef serviceID, CFStringRef entity,
     else {
        if (old_val == NULL || CFEqual(new_val, old_val) == FALSE) {
            if ((S_IPMonitor_debug & kDebugFlag1) != 0) {
-               dump_service_entity(serviceID, entity,
-                                   CFSTR("Changed: old"), old_val);
-               dump_service_entity(serviceID, entity,
-                                   CFSTR("Changed: new"), new_val);
+               log_service_entity(LOG_DEBUG, serviceID, entity,
+                                  CFSTR("Changed: old"), old_val);
+               log_service_entity(LOG_DEBUG, serviceID, entity,
+                                  CFSTR("Changed: new"), new_val);
            }
            CFDictionarySetValue(service_dict, entity, new_val);
            changed = TRUE;
@@ -1576,7 +1759,7 @@ copy_dhcp_hostname(CFStringRef serviceID)
     }
 
     service_dict =
-       CFDictionaryGetValue(dict, kSCEntNetIPv4ServiceDict);
+       CFDictionaryGetValue(dict, kIPv4DictService);
 
     if (service_dict == NULL
        || isA_CFDictionary(service_dict) == NULL) {
@@ -1593,8 +1776,9 @@ copy_dhcp_hostname(CFStringRef serviceID)
     return (hostname);
 }
 
-static boolean_t
-ipv6_service_dict_set(CFStringRef serviceID, CFDictionaryRef new_val)
+#if    !TARGET_IPHONE_SIMULATOR
+static void
+ipv6_service_update_router(CFStringRef serviceID, CFDictionaryRef new_val)
 {
 #ifdef SIOCDRADD_IN6
     int                        if_index;
@@ -1626,15 +1810,16 @@ ipv6_service_dict_set(CFStringRef serviceID, CFDictionaryRef new_val)
     }
     s = inet6_dgram_socket();
     if (s < 0) {
-       syslog(LOG_ERR,
-              "IPMonitor: ipv6_service_dict_set: socket failed, %s",
+       my_log(LOG_ERR,
+              "IPMonitor: ipv6_service_update_router: socket failed, %s",
               strerror(errno));
        goto done;
     }
     if (new_val != NULL) {
        new_router = CFDictionaryGetValue(new_val, kSCPropNetIPv6Router);
     }
-    if (old_router != NULL
+    if (S_dict_get_boolean(old_val, kIsNULL, FALSE) == FALSE
+       && old_router != NULL
        && (new_router == NULL || CFEqual(old_router, new_router) == FALSE)) {
        /* remove the old Router */
        if (cfstring_to_ip6(old_router, &router_ip)) {
@@ -1645,7 +1830,7 @@ ipv6_service_dict_set(CFStringRef serviceID, CFDictionaryRef new_val)
            }
            if (siocdrdel_in6(s, if_index, &router_ip) < 0) {
                if (errno != EINVAL) {
-                   syslog(LOG_ERR,
+                   my_log(LOG_ERR,
                           "IPMonitor: siocdrdel_in6(%s, %s) failed, %s",
                           ifn,
                           inet_ntop(AF_INET6, &router_ip,
@@ -1654,7 +1839,7 @@ ipv6_service_dict_set(CFStringRef serviceID, CFDictionaryRef new_val)
                }
            }
            else if (S_IPMonitor_debug & kDebugFlag1) {
-               syslog(LOG_NOTICE,
+               my_log(LOG_DEBUG,
                       "IPMonitor: %s removed default route %s",
                       ifn,
                       inet_ntop(AF_INET6, &router_ip,
@@ -1663,7 +1848,8 @@ ipv6_service_dict_set(CFStringRef serviceID, CFDictionaryRef new_val)
        }
     }
     /* add the new Router */
-    if (cfstring_to_ip6(new_router, &router_ip)) {
+    if (S_dict_get_boolean(new_val, kIsNULL, FALSE) == FALSE
+       && cfstring_to_ip6(new_router, &router_ip)) {
        if (IN6_IS_ADDR_LINKLOCAL(&router_ip) ||
            IN6_IS_ADDR_MC_LINKLOCAL(&router_ip)) {
            /* scope it */
@@ -1671,7 +1857,7 @@ ipv6_service_dict_set(CFStringRef serviceID, CFDictionaryRef new_val)
        }
        if (siocdradd_in6(s, if_index, &router_ip, 0) < 0) {
            if (errno != EINVAL) {
-               syslog(LOG_ERR,
+               my_log(LOG_ERR,
                       "IPMonitor: siocdradd_in6(%s, %s) failed, %s",
                       ifn,
                       inet_ntop(AF_INET6, &router_ip,
@@ -1680,7 +1866,7 @@ ipv6_service_dict_set(CFStringRef serviceID, CFDictionaryRef new_val)
            }
        }
        else if (S_IPMonitor_debug & kDebugFlag1) {
-           syslog(LOG_NOTICE,
+           my_log(LOG_DEBUG,
                   "IPMonitor: %s added default route %s",
                   ifn,
                   inet_ntop(AF_INET6, &router_ip,
@@ -1689,10 +1875,11 @@ ipv6_service_dict_set(CFStringRef serviceID, CFDictionaryRef new_val)
     }
     close(s);
 
- done:
 done:
 #endif /* SIOCDRADD_IN6 */
-    return (service_dict_set(serviceID, kSCEntNetIPv6, new_val));
+    return;
 }
+#endif /* !TARGET_IPHONE_SIMULATOR */
 
 #define        ALLOW_EMPTY_STRING      0x1
 
@@ -1863,19 +2050,19 @@ get_ipv4_changes(CFStringRef serviceID, CFDictionaryRef state_dict,
        }
     }
     else {
-       SCLog(TRUE, LOG_NOTICE,
-             CFSTR("IPMonitor: %@ invalid IPv4 dictionary = %@"),
-             serviceID,
-             dict);
+       my_log(LOG_NOTICE,
+              "IPMonitor: %@ invalid IPv4 dictionary = %@",
+              serviceID,
+              dict);
     }
   done:
     if (routes_data != NULL) {
        CFStringRef     keys[2];
        CFTypeRef       values[2];
 
-       keys[0] = kSCEntNetIPv4ServiceDict;
+       keys[0] = kIPv4DictService;
        values[0] = dict;
-       keys[1] = kSCEntNetIPv4RouteList;
+       keys[1] = kIPv4DictRoutes;
        values[1] = routes_data;
 
        aggregated_dict = CFDictionaryCreate(NULL,
@@ -1920,9 +2107,9 @@ get_ipv6_changes(CFStringRef serviceID, CFDictionaryRef state_dict,
     }
     if (valid_ip == FALSE) {
        if ((S_IPMonitor_debug & kDebugFlag1) != 0) {
-           SCLog(TRUE, LOG_NOTICE,
-                 CFSTR("IPMonitor: %@ has no valid IPv6 address, ignoring"),
-                 serviceID);
+           my_log(LOG_DEBUG,
+                  "IPMonitor: %@ has no valid IPv6 address, ignoring",
+                  serviceID);
        }
        goto done;
     }
@@ -1947,7 +2134,12 @@ get_ipv6_changes(CFStringRef serviceID, CFDictionaryRef state_dict,
     new_dict = dict;
 
  done:
-    changed = ipv6_service_dict_set(serviceID, new_dict);
+
+#if    !TARGET_IPHONE_SIMULATOR
+    ipv6_service_update_router(serviceID, new_dict);
+#endif /* !TARGET_IPHONE_SIMULATOR */
+
+    changed = service_dict_set(serviceID, kSCEntNetIPv6, new_dict);
     if (new_dict == NULL) {
        /* clean up the rank too */
        CFDictionaryRemoveValue(S_ipv6_service_rank_dict, serviceID);
@@ -1965,18 +2157,21 @@ accumulate_dns_servers(CFArrayRef in_servers, ProtocolFlags active_protos,
 
     count = CFArrayGetCount(in_servers);
     for (i = 0; i < count; i++) {
-       CFStringRef     addr = CFArrayGetValueAtIndex(in_servers, i);
+       CFStringRef     addr;
        struct in6_addr ipv6_addr;
        struct in_addr  ip_addr;
 
+       addr = CFArrayGetValueAtIndex(in_servers, i);
+       assert(addr != NULL);
+
        if (cfstring_to_ip(addr, &ip_addr)) {
            /* IPv4 address */
            if ((active_protos & kProtocolFlagsIPv4) == 0
                && ntohl(ip_addr.s_addr) != INADDR_LOOPBACK) {
                if ((S_IPMonitor_debug & kDebugFlag1) != 0) {
-                   syslog(LOG_NOTICE,
+                   my_log(LOG_DEBUG,
                           "IPMonitor: no IPv4 connectivity, "
-                          "ignoring DNS server address " IP_FORMAT,
+                          "ignoring DNS server address ", IP_FORMAT,
                           IP_LIST(&ip_addr));
                }
                continue;
@@ -1991,11 +2186,11 @@ accumulate_dns_servers(CFArrayRef in_servers, ProtocolFlags active_protos,
                if ((S_IPMonitor_debug & kDebugFlag1) != 0) {
                    char        ntopbuf[INET6_ADDRSTRLEN];
 
-                   syslog(LOG_NOTICE,
+                   my_log(LOG_DEBUG,
                           "IPMonitor: no IPv6 connectivity, "
                           "ignoring DNS server address %s",
-                          inet_ntop(AF_INET6, &ipv6_addr,
-                                    ntopbuf, sizeof(ntopbuf)));
+                           inet_ntop(AF_INET6, &ipv6_addr,
+                                     ntopbuf, sizeof(ntopbuf)));
                }
                continue;
            }
@@ -2015,9 +2210,9 @@ accumulate_dns_servers(CFArrayRef in_servers, ProtocolFlags active_protos,
        }
        else {
            /* bad IP address */
-           SCLog(TRUE, LOG_NOTICE,
-                 CFSTR("IPMonitor: ignoring bad DNS server address '%@'"),
-                 addr);
+           my_log(LOG_NOTICE,
+                  "IPMonitor: ignoring bad DNS server address '%@'",
+                  addr);
            continue;
        }
 
@@ -2127,6 +2322,8 @@ get_dns_changes(CFStringRef serviceID, CFDictionaryRef state_dict,
        kSCPropNetDNSSearchOrder,
        kSCPropNetDNSServerPort,
        kSCPropNetDNSServerTimeout,
+       kSCPropNetDNSServiceIdentifier,
+       kSCPropNetDNSSupplementalMatchDomainsNoSearch,
     };
     IPv4RouteListRef           routes = NULL;
 
@@ -2216,7 +2413,7 @@ get_dns_changes(CFStringRef serviceID, CFDictionaryRef state_dict,
     }
 
     if (active_protos == kProtocolFlagsNone) {
-       /* there is no IPv4 nor IPv6, only supplemental DNS */
+       /* there is no IPv4 nor IPv6, only supplemental or service-specific DNS */
        if (CFDictionaryContainsKey(new_dict,
                                    kSCPropNetDNSSupplementalMatchDomains)) {
            /* only keep State: supplemental */
@@ -2224,6 +2421,18 @@ get_dns_changes(CFStringRef serviceID, CFDictionaryRef state_dict,
            CFDictionaryRemoveValue(new_dict, kSCPropNetDNSSearchDomains);
            CFDictionaryRemoveValue(new_dict, kSCPropNetDNSSearchOrder);
            CFDictionaryRemoveValue(new_dict, kSCPropNetDNSSortList);
+
+           if ((interface == NULL) && (setup_dict == NULL) && (state_dict != NULL)) {
+               /*
+                * for supplemental-only configurations, add any scoped (or
+                * wild-card "*") interface
+                */
+               interface = CFDictionaryGetValue(state_dict, kSCPropInterfaceName);
+           }
+       } else if (CFDictionaryContainsKey(new_dict, kSCPropNetDNSServiceIdentifier) &&
+                  (interface == NULL) &&
+                  (state_dict != NULL)) {
+           interface = CFDictionaryGetValue(state_dict, kSCPropInterfaceName);
        } else {
            goto done;
        }
@@ -2663,11 +2872,67 @@ services_info_get_interface(CFDictionaryRef services_info,
     return (interface);
 }
 
+
+
+static const CFStringRef *statusEntityNames[] = {
+    &kSCEntNetIPSec,
+    &kSCEntNetPPP,
+    &kSCEntNetVPN,
+};
+
+static Boolean
+get_transient_service_changes(CFStringRef serviceID, CFDictionaryRef services_info)
+{
+    boolean_t  changed = FALSE;
+    int                i;
+
+    static const struct {
+       const CFStringRef       *entityName;
+       const CFStringRef       *statusKey;
+    } transientServiceInfo[] = {
+       { &kSCEntNetIPSec,      &kSCPropNetIPSecStatus  },
+       { &kSCEntNetPPP,        &kSCPropNetPPPStatus    },
+       { &kSCEntNetVPN,        &kSCPropNetVPNStatus    },
+    };
+
+    for (i = 0; i < sizeof(transientServiceInfo)/sizeof(transientServiceInfo[0]); i++) {
+       CFDictionaryRef         dict;
+       CFNumberRef             status          = NULL;
+       CFMutableDictionaryRef  ts_dict         = NULL;
+
+       dict = get_service_state_entity(services_info, serviceID, *transientServiceInfo[i].entityName);
+
+       if (isA_CFDictionary(dict) != NULL) {
+           status = CFDictionaryGetValue(dict, *transientServiceInfo[i].statusKey);
+       }
+
+       if (isA_CFNumber(status) != NULL) {
+           ts_dict = CFDictionaryCreateMutable(NULL,
+                                                0,
+                                                &kCFTypeDictionaryKeyCallBacks,
+                                                &kCFTypeDictionaryValueCallBacks);
+           CFDictionaryAddValue(ts_dict,
+                                *transientServiceInfo[i].statusKey,
+                                status);
+       }
+
+       if (service_dict_set(serviceID, *transientServiceInfo[i].entityName, ts_dict)) {
+           changed = TRUE;
+       }
+
+       if (ts_dict != NULL) {
+           CFRelease(ts_dict);
+       }
+    }
+    return (changed);
+}
+
 static boolean_t
 get_rank_changes(CFStringRef serviceID, CFDictionaryRef state_options,
                 CFDictionaryRef setup_options, CFDictionaryRef services_info)
 {
     boolean_t                  changed         = FALSE;
+    CFBooleanRef               ip_is_coupled   = NULL;
     CFMutableDictionaryRef      new_dict       = NULL;
     CFStringRef                        new_rank        = NULL;
     CFStringRef                        setup_rank      = NULL;
@@ -2683,13 +2948,28 @@ get_rank_changes(CFStringRef serviceID, CFDictionaryRef state_options,
      *
      * Note 2: Rank Never > Rank Last > Rank First > Rank None
      */
-    if (isA_CFDictionary(setup_options)) {
-       setup_rank = CFDictionaryGetValue(setup_options, kSCPropNetServicePrimaryRank);
-       setup_rank = isA_CFString(setup_rank);
-    }
     if (isA_CFDictionary(state_options)) {
-       state_rank = CFDictionaryGetValue(state_options, kSCPropNetServicePrimaryRank);
+       CFBooleanRef    coupled;
+
+       state_rank
+           = CFDictionaryGetValue(state_options, kSCPropNetServicePrimaryRank);
        state_rank = isA_CFString(state_rank);
+       coupled = CFDictionaryGetValue(state_options, kIPIsCoupled);
+       if (isA_CFBoolean(coupled) != NULL) {
+           ip_is_coupled = coupled;
+       }
+    }
+    if (isA_CFDictionary(setup_options)) {
+       CFBooleanRef    coupled;
+
+       setup_rank
+           = CFDictionaryGetValue(setup_options, kSCPropNetServicePrimaryRank);
+       setup_rank = isA_CFString(setup_rank);
+
+       coupled = CFDictionaryGetValue(setup_options, kIPIsCoupled);
+       if (isA_CFBoolean(coupled) != NULL) {
+           ip_is_coupled = coupled;
+       }
     }
 
     if (((setup_rank != NULL) && CFEqual(setup_rank, kSCValNetServicePrimaryRankNever)) ||
@@ -2716,21 +2996,31 @@ get_rank_changes(CFStringRef serviceID, CFDictionaryRef state_options,
        if (interface != NULL) {
            new_rank = CFDictionaryGetValue(S_if_rank_dict, interface);
            if (S_IPMonitor_debug & kDebugFlag1) {
-               SCLog(TRUE, LOG_NOTICE,
-                     CFSTR("serviceID %@ interface %@ rank = %@"),
-                     serviceID, interface,
-                     (new_rank != NULL) ? new_rank : CFSTR("<none>"));
+               my_log(LOG_DEBUG,
+                      "serviceID %@ interface %@ rank = %@",
+                      serviceID, interface,
+                      (new_rank != NULL) ? new_rank : CFSTR("<none>"));
            }
        }
     }
 
-    if (new_rank != NULL) {
+
+    if (ip_is_coupled != NULL && CFBooleanGetValue(ip_is_coupled) == FALSE) {
+       /* don't bother setting a value if it's the default */
+       ip_is_coupled = NULL;
+    }
+    if (new_rank != NULL || ip_is_coupled != NULL) {
        new_dict = CFDictionaryCreateMutable(NULL, 0,
                                             &kCFTypeDictionaryKeyCallBacks,
                                             &kCFTypeDictionaryValueCallBacks);
-       CFDictionarySetValue(new_dict, kSCPropNetServicePrimaryRank, new_rank);
+       if (new_rank != NULL) {
+           CFDictionarySetValue(new_dict, kSCPropNetServicePrimaryRank,
+                                new_rank);
+       }
+       if (ip_is_coupled != NULL) {
+           CFDictionarySetValue(new_dict, kIPIsCoupled, kCFBooleanTrue);
+       }
     }
-
     changed = service_dict_set(serviceID, kSCEntNetService, new_dict);
     my_CFRelease(&new_dict);
     return (changed);
@@ -2758,14 +3048,14 @@ if_rank_set(CFStringRef ifname, CFDictionaryRef rank_dict)
     /* specific rank is asserted */
     if (rank != NULL) {
        if (S_IPMonitor_debug & kDebugFlag1) {
-           SCLog(TRUE, LOG_NOTICE, CFSTR("Interface %@ asserted rank %@"),
-                 ifname, rank);
+           my_log(LOG_DEBUG, "Interface %@ asserted rank %@",
+                  ifname, rank);
        }
        CFDictionarySetValue(S_if_rank_dict, ifname, rank);
     } else {
        if (S_IPMonitor_debug & kDebugFlag1) {
-           SCLog(TRUE, LOG_NOTICE, CFSTR("Interface %@ removed rank."),
-                 ifname);
+           my_log(LOG_DEBUG, "Interface %@ removed rank",
+                  ifname);
        }
        CFDictionaryRemoveValue(S_if_rank_dict, ifname);
     }
@@ -2843,10 +3133,59 @@ add_service_keys(CFStringRef serviceID, CFMutableArrayRef keys, CFMutableArrayRe
     CFArrayAppendValue(patterns, key);
     CFRelease(key);
 
+    return;
+}
+
+static void
+add_status_keys(CFStringRef service_id, CFMutableArrayRef patterns)
+{
+    int            i;
+
+    for (i = 0; i < sizeof(statusEntityNames)/sizeof(statusEntityNames[0]); i++) {
+       CFStringRef     pattern;
+
+       pattern = state_service_key(service_id, *statusEntityNames[i]);
+       CFArrayAppendValue(patterns, pattern);
+       CFRelease(pattern);
+    }
 
     return;
 }
 
+static const CFStringRef *reachabilitySetupKeys[] = {
+    &kSCEntNetPPP,
+    &kSCEntNetInterface,
+    &kSCEntNetIPv4,
+    &kSCEntNetIPv6,
+};
+
+
+static void
+add_reachability_keys(CFMutableArrayRef patterns)
+{
+    int                i;
+
+    for (i = 0; i < sizeof(reachabilitySetupKeys)/(sizeof(reachabilitySetupKeys[0])); i++)
+    {
+       CFStringRef pattern;
+       pattern = setup_service_key(kSCCompAnyRegex, *reachabilitySetupKeys[i]);
+       CFArrayAppendValue(patterns, pattern);
+       CFRelease(pattern);
+    }
+}
+
+
+static void
+add_vpn_keys(CFMutableArrayRef patterns)
+{
+    CFStringRef        pattern;
+
+    pattern = setup_service_key(kSCCompAnyRegex, kSCEntNetVPN);
+    CFArrayAppendValue(patterns, pattern);
+    CFRelease(pattern);
+}
+
+
 static CFDictionaryRef
 services_info_copy(SCDynamicStoreRef session, CFArrayRef service_list,
                   CFArrayRef if_rank_list)
@@ -2870,8 +3209,13 @@ services_info_copy(SCDynamicStoreRef session, CFArrayRef service_list,
        CFStringRef     serviceID = CFArrayGetValueAtIndex(service_list, s);
 
        add_service_keys(serviceID, get_keys, get_patterns);
+       add_status_keys(serviceID, get_keys);
     }
 
+    add_reachability_keys(get_patterns);
+
+    add_vpn_keys(get_patterns);
+
     if_count = (if_rank_list != NULL)
               ? CFArrayGetCount(if_rank_list) : 0;
     for (s = 0; s < if_count; s++) {
@@ -2889,20 +3233,24 @@ services_info_copy(SCDynamicStoreRef session, CFArrayRef service_list,
     return (info);
 }
 
-static int                     rtm_seq = 0;
+#if    !TARGET_IPHONE_SIMULATOR
+static int     rtm_seq = 0;
+#endif /* !TARGET_IPHONE_SIMULATOR */
 
+#if    !TARGET_IPHONE_SIMULATOR
 static int
 route_open_socket(void)
 {
     int sockfd;
 
     if ((sockfd = socket(PF_ROUTE, SOCK_RAW, PF_ROUTE)) == -1) {
-       SCLog(TRUE, LOG_NOTICE,
-             CFSTR("IPMonitor: route_open_socket: socket failed, %s"),
-             strerror(errno));
+       my_log(LOG_NOTICE,
+              "IPMonitor: route_open_socket: socket failed, %s",
+              strerror(errno));
     }
     return (sockfd);
 }
+#endif /* !TARGET_IPHONE_SIMULATOR */
 
 /*
  * Define: ROUTE_MSG_ADDRS_SPACE
@@ -2919,6 +3267,7 @@ typedef struct {
     char               addrs[ROUTE_MSG_ADDRS_SPACE];
 } route_msg;
 
+#if    !TARGET_IPHONE_SIMULATOR
 static int
 ipv4_route(int sockfd,
           int cmd, struct in_addr gateway, struct in_addr netaddr,
@@ -2941,11 +3290,16 @@ ipv4_route(int sockfd,
 
     if (ifname == NULL) {
        /* this should not happen, but rather than crash, return an error */
-       syslog(LOG_NOTICE,
+       my_log(LOG_NOTICE,
               "IPMonitor: ipv4_route ifname is NULL on network address %s",
               inet_ntoa(netaddr));
        return (EBADF);
     }
+    if ((flags & kRouteIsNULLFlag) != 0) {
+       my_log(LOG_DEBUG, "IPMonitor: ignoring route %s on %s",
+              inet_ntoa(netaddr), ifname);
+       return (0);
+    }
     memset(&rtmsg, 0, sizeof(rtmsg));
     rtmsg.hdr.rtm_type = cmd;
     rtmsg.hdr.rtm_version = RTM_VERSION;
@@ -2966,7 +3320,7 @@ ipv4_route(int sockfd,
        }
        if (ifindex == 0) {
            /* specifically asked for a scoped route, yet no index supplied */
-           syslog(LOG_NOTICE,
+           my_log(LOG_NOTICE,
                   "IPMonitor: ipv4_route index is 0 on %s-scoped route %s",
                   ifname, inet_ntoa(netaddr));
            return (EBADF);
@@ -3029,7 +3383,9 @@ ipv4_route(int sockfd,
     }
     return (ret);
 }
+#endif /* !TARGET_IPHONE_SIMULATOR */
 
+#if    !TARGET_IPHONE_SIMULATOR
 static boolean_t
 ipv6_route(int cmd, struct in6_addr gateway, struct in6_addr netaddr,
           struct in6_addr netmask, char * ifname, boolean_t is_direct)
@@ -3110,9 +3466,9 @@ ipv6_route(int cmd, struct in6_addr gateway, struct in6_addr netaddr,
        }
        else {
            if ((S_IPMonitor_debug & kDebugFlag1) != 0) {
-               SCLog(TRUE, LOG_NOTICE,
-                     CFSTR("IPMonitor ipv6_route: write routing"
-                           " socket failed, %s"), strerror(errno));
+               my_log(LOG_DEBUG,
+                      "IPMonitor ipv6_route: write routing"
+                      " socket failed, %s", strerror(errno));
            }
            ret = FALSE;
        }
@@ -3126,7 +3482,7 @@ static boolean_t
 ipv6_default_route_delete(void)
 {
     if ((S_IPMonitor_debug & kDebugFlag1) != 0) {
-       SCLog(TRUE, LOG_NOTICE, CFSTR("IPMonitor: IPv6 route delete default"));
+       my_log(LOG_DEBUG, "IPMonitor: IPv6 route delete default");
     }
     return (ipv6_route(RTM_DELETE, S_ip6_zeros, S_ip6_zeros, S_ip6_zeros,
                       NULL, FALSE));
@@ -3139,17 +3495,19 @@ ipv6_default_route_add(struct in6_addr router, char * ifname,
     if ((S_IPMonitor_debug & kDebugFlag1) != 0) {
        char    ntopbuf[INET6_ADDRSTRLEN];
 
-       SCLog(TRUE, LOG_NOTICE,
-             CFSTR("IPMonitor: IPv6 route add default"
-                   " %s interface %s direct %d"),
-             inet_ntop(AF_INET6, &router, ntopbuf, sizeof(ntopbuf)),
-             ifname, is_direct);
+       my_log(LOG_DEBUG,
+              "IPMonitor: IPv6 route add default"
+              " %s interface %s direct %d",
+              inet_ntop(AF_INET6, &router, ntopbuf, sizeof(ntopbuf)),
+              ifname, is_direct);
     }
     return (ipv6_route(RTM_ADD, router, S_ip6_zeros, S_ip6_zeros,
                       ifname, is_direct));
 }
+#endif /* !TARGET_IPHONE_SIMULATOR */
 
 
+#if    !TARGET_IPHONE_SIMULATOR
 static int
 multicast_route_delete(int sockfd)
 {
@@ -3171,7 +3529,9 @@ multicast_route_add(int sockfd)
     return (ipv4_route(sockfd, RTM_ADD, gateway, netaddr, netmask, "lo0", 0,
                       gateway, 0));
 }
+#endif /* !TARGET_IPHONE_SIMULATOR */
 
+#if    !TARGET_IPHONE_SIMULATOR
 #ifdef RTF_IFSCOPE
 static void
 set_ipv6_default_interface(char * ifname)
@@ -3190,15 +3550,15 @@ set_ipv6_default_interface(char * ifname)
 
     sock = inet6_dgram_socket();
     if (sock == -1) {
-       SCLog(TRUE, LOG_ERR,
-             CFSTR("IPMonitor: set_ipv6_default_interface: socket failed, %s"),
-             strerror(errno));
+       my_log(LOG_ERR,
+              "IPMonitor: set_ipv6_default_interface: socket failed, %s",
+              strerror(errno));
        return;
     }
     if (ioctl(sock, SIOCSDEFIFACE_IN6, (caddr_t)&ndifreq) == -1) {
-       SCLog(TRUE, LOG_ERR,
-             CFSTR("IPMonitor: set_ipv6_default_interface: ioctl(SIOCSDEFIFACE_IN6) failed, %s"),
-             strerror(errno));
+       my_log(LOG_ERR,
+              "IPMonitor: set_ipv6_default_interface: ioctl(SIOCSDEFIFACE_IN6) failed, %s",
+              strerror(errno));
     }
     close(sock);
     return;
@@ -3215,6 +3575,7 @@ set_ipv6_router(struct in6_addr * router, char * ifname, boolean_t is_direct)
     }
     return;
 }
+#endif /* !TARGET_IPHONE_SIMULATOR */
 
 #if    !TARGET_OS_IPHONE
 static __inline__ void
@@ -3296,6 +3657,7 @@ set_dns(CFArrayRef val_search_domains,
 }
 #endif /* !TARGET_OS_IPHONE */
 
+#if    !TARGET_IPHONE_SIMULATOR
 static boolean_t
 router_is_our_ipv6_address(CFStringRef router, CFArrayRef addr_list)
 {
@@ -3314,19 +3676,44 @@ router_is_our_ipv6_address(CFStringRef router, CFArrayRef addr_list)
     }
     return (FALSE);
 }
+#endif /* !TARGET_IPHONE_SIMULATOR */
 
 static IPv4RouteListRef
 service_dict_get_ipv4_routelist(CFDictionaryRef service_dict)
 {
     CFDictionaryRef    dict;
-    IPv4RouteListRef   routes = NULL;
 
     dict = CFDictionaryGetValue(service_dict, kSCEntNetIPv4);
 
-    routes = ipv4_dict_get_routelist(dict);
-    return (routes);
+    return (ipv4_dict_get_routelist(dict));
+}
+
+static CFStringRef
+service_dict_get_ipv4_ifname(CFDictionaryRef service_dict)
+{
+    CFDictionaryRef    dict;
+
+    dict = CFDictionaryGetValue(service_dict, kSCEntNetIPv4);
+    return (ipv4_dict_get_ifname(dict));
 }
 
+static boolean_t
+service_get_ip_is_coupled(CFStringRef serviceID)
+{
+    CFDictionaryRef    dict;
+    boolean_t          ip_is_coupled = FALSE;
+
+    dict = service_dict_get(serviceID, kSCEntNetService);
+    if (dict != NULL) {
+       if (CFDictionaryContainsKey(dict, kIPIsCoupled)) {
+           ip_is_coupled = TRUE;
+       }
+    }
+    return (ip_is_coupled);
+}
+
+#if    !TARGET_IPHONE_SIMULATOR
+
 typedef struct apply_ipv4_route_context {
     IPv4RouteListRef   old;
     IPv4RouteListRef   new;
@@ -3372,14 +3759,14 @@ apply_ipv4_route(IPv4RouteListApplyCommand cmd, IPv4RouteRef route, void * arg)
                                            ifn_p, route);
            }
            if (retval != 0) {
-               SCLog(TRUE, LOG_NOTICE,
-                     CFSTR("IPMonitor apply_ipv4_route failed to add"
-                           " %s/32 route, %s"),
-                     inet_ntoa(route->gateway), strerror(retval));
+               my_log(LOG_NOTICE,
+                      "IPMonitor apply_ipv4_route failed to add"
+                      " %s/32 route, %s",
+                      inet_ntoa(route->gateway), strerror(retval));
            }
            else if ((S_IPMonitor_debug & kDebugFlag1) != 0) {
-               SCLog(TRUE, LOG_NOTICE, CFSTR("Added IPv4 Route %s/32"),
-                     inet_ntoa(route->gateway));
+               my_log(LOG_DEBUG, "Added IPv4 Route %s/32",
+                      inet_ntoa(route->gateway));
            }
        }
        retval = ipv4_route(context->sockfd,
@@ -3399,16 +3786,16 @@ apply_ipv4_route(IPv4RouteListApplyCommand cmd, IPv4RouteRef route, void * arg)
                                route->ifa, route->flags);
        }
        if (retval != 0) {
-           SCLog(TRUE, LOG_NOTICE,
-                 CFSTR("IPMonitor apply_ipv4_route failed to add"
-                       " route, %s:"), strerror(retval));
-           IPv4RouteLog(route);
+           my_log(LOG_NOTICE,
+                  "IPMonitor apply_ipv4_route failed to add"
+                  " route, %s:", strerror(retval));
+           IPv4RouteLog(LOG_NOTICE, route);
        }
        else if ((S_IPMonitor_debug & kDebugFlag1) != 0) {
-           SCLog(TRUE, LOG_NOTICE,
-                 CFSTR("Added IPv4 route new[%d] = "),
-                 route - context->new->list);
-           IPv4RouteLog(route);
+           my_log(LOG_DEBUG,
+                  "Added IPv4 route new[%d] = ",
+                  route - context->new->list);
+           IPv4RouteLog(LOG_DEBUG, route);
        }
        break;
     case kIPv4RouteListRemoveRouteCommand:
@@ -3418,30 +3805,30 @@ apply_ipv4_route(IPv4RouteListApplyCommand cmd, IPv4RouteRef route, void * arg)
                            route->ifa, route->flags);
        if (retval != 0) {
            if (retval != ESRCH) {
-               SCLog(TRUE, LOG_NOTICE,
-                     CFSTR("IPMonitor apply_ipv4_route failed to remove"
-                           " route, %s: "), strerror(retval));
-               IPv4RouteLog(route);
+               my_log(LOG_NOTICE,
+                      "IPMonitor apply_ipv4_route failed to remove"
+                      " route, %s: ", strerror(retval));
+               IPv4RouteLog(LOG_NOTICE, route);
            }
        }
        else if ((S_IPMonitor_debug & kDebugFlag1) != 0) {
-           SCLog(TRUE, LOG_NOTICE,
-                 CFSTR("Removed IPv4 route old[%d] = "),
-                 route - context->old->list);
-           IPv4RouteLog(route);
+           my_log(LOG_DEBUG,
+                  "Removed IPv4 route old[%d] = ",
+                  route - context->old->list);
+           IPv4RouteLog(LOG_DEBUG, route);
        }
        if ((route->flags & kRouteIsNotSubnetLocalFlag) != 0) {
            retval = ipv4_route_gateway(context->sockfd, RTM_DELETE,
                                        ifn_p, route);
            if (retval != 0) {
-               SCLog(TRUE, LOG_NOTICE,
-                     CFSTR("IPMonitor apply_ipv4_route failed to remove"
-                           " %s/32 route, %s: "),
-                     inet_ntoa(route->gateway), strerror(retval));
+               my_log(LOG_NOTICE,
+                      "IPMonitor apply_ipv4_route failed to remove"
+                      " %s/32 route, %s: ",
+                      inet_ntoa(route->gateway), strerror(retval));
            }
            else if ((S_IPMonitor_debug & kDebugFlag1) != 0) {
-               SCLog(TRUE, LOG_NOTICE, CFSTR("Removed IPv4 Route %s/32"),
-                     inet_ntoa(route->gateway));
+               my_log(LOG_DEBUG, "Removed IPv4 Route %s/32",
+                      inet_ntoa(route->gateway));
            }
        }
        break;
@@ -3450,6 +3837,7 @@ apply_ipv4_route(IPv4RouteListApplyCommand cmd, IPv4RouteRef route, void * arg)
     }
     return;
 }
+#endif /* !TARGET_IPHONE_SIMULATOR */
 
 /*
  * Function: update_ipv4
@@ -3465,7 +3853,9 @@ update_ipv4(CFStringRef           primary,
            IPv4RouteListRef    new_routelist,
            keyChangeListRef    keys)
 {
+#if    !TARGET_IPHONE_SIMULATOR
     apply_ipv4_route_context_t context;
+#endif /* !TARGET_IPHONE_SIMULATOR */
 
     if (keys != NULL) {
        if (new_routelist != NULL && primary != NULL) {
@@ -3515,23 +3905,24 @@ update_ipv4(CFStringRef         primary,
        }
     }
 
+#if    !TARGET_IPHONE_SIMULATOR
     bzero(&context, sizeof(context));
     context.sockfd = route_open_socket();
     if (context.sockfd != -1) {
        if ((S_IPMonitor_debug & kDebugFlag1) != 0) {
            if (S_ipv4_routelist == NULL) {
-               SCLog(TRUE, LOG_NOTICE, CFSTR("Old Routes = <none>"));
+               my_log(LOG_DEBUG, "Old Routes = <none>");
            }
            else {
-               SCLog(TRUE, LOG_NOTICE, CFSTR("Old Routes = "));
-               IPv4RouteListLog(S_ipv4_routelist);
+               my_log(LOG_DEBUG, "Old Routes = ");
+               IPv4RouteListLog(LOG_DEBUG, S_ipv4_routelist);
            }
            if (new_routelist == NULL) {
-               SCLog(TRUE, LOG_NOTICE, CFSTR("New Routes = <none>"));
+               my_log(LOG_DEBUG, "New Routes = <none>");
            }
            else {
-               SCLog(TRUE, LOG_NOTICE, CFSTR("New Routes = "));
-               IPv4RouteListLog(new_routelist);
+               my_log(LOG_DEBUG, "New Routes = ");
+               IPv4RouteListLog(LOG_DEBUG, new_routelist);
            }
        }
        context.old = S_ipv4_routelist;
@@ -3550,64 +3941,75 @@ update_ipv4(CFStringRef         primary,
        free(S_ipv4_routelist);
     }
     S_ipv4_routelist = new_routelist;
+#endif /* !TARGET_IPHONE_SIMULATOR */
+
     return;
 }
 
 static void
-update_ipv6(CFDictionaryRef    services_info,
-           CFStringRef         primary,
+update_ipv6(CFStringRef                primary,
            keyChangeListRef    keys)
 {
     CFDictionaryRef    ipv6_dict = NULL;
 
     if (primary != NULL) {
-       CFDictionaryRef service_dict;
-
-       service_dict = CFDictionaryGetValue(S_service_state_dict, primary);
-       if (service_dict != NULL) {
-           ipv6_dict = CFDictionaryGetValue(service_dict, kSCEntNetIPv6);
-       }
+       ipv6_dict = service_dict_get(primary, kSCEntNetIPv6);
     }
     if (ipv6_dict != NULL) {
+#if    !TARGET_IPHONE_SIMULATOR
        CFArrayRef              addrs;
+#endif /* !TARGET_IPHONE_SIMULATOR */
        CFMutableDictionaryRef  dict = NULL;
        CFStringRef             if_name = NULL;
+#if    !TARGET_IPHONE_SIMULATOR
        char                    ifn[IFNAMSIZ] = { '\0' };
        char *                  ifn_p = NULL;
        boolean_t               is_direct = FALSE;
+#endif /* !TARGET_IPHONE_SIMULATOR */
        CFStringRef             val_router = NULL;
 
        dict = CFDictionaryCreateMutable(NULL, 0,
                                         &kCFTypeDictionaryKeyCallBacks,
                                         &kCFTypeDictionaryValueCallBacks);
-       val_router = CFDictionaryGetValue(ipv6_dict, kSCPropNetIPv6Router);
+
+#if    !TARGET_IPHONE_SIMULATOR
        addrs = CFDictionaryGetValue(ipv6_dict,
                                     kSCPropNetIPv6Addresses);
+#endif /* !TARGET_IPHONE_SIMULATOR */
+
+       val_router = CFDictionaryGetValue(ipv6_dict, kSCPropNetIPv6Router);
        if (val_router != NULL) {
-           /* no router if router is one of our IP addresses */
+#if    !TARGET_IPHONE_SIMULATOR
            is_direct = router_is_our_ipv6_address(val_router, addrs);
+#endif /* !TARGET_IPHONE_SIMULATOR */
+           /* no router if router is one of our IP addresses */
            CFDictionarySetValue(dict, kSCPropNetIPv6Router,
                                 val_router);
        }
+#if    !TARGET_IPHONE_SIMULATOR
        else {
            val_router = CFArrayGetValueAtIndex(addrs, 0);
            is_direct = TRUE;
        }
+#endif /* !TARGET_IPHONE_SIMULATOR */
        if_name = CFDictionaryGetValue(ipv6_dict, kSCPropInterfaceName);
        if (if_name) {
            CFDictionarySetValue(dict,
                                 kSCDynamicStorePropNetPrimaryInterface,
                                 if_name);
+#if    !TARGET_IPHONE_SIMULATOR
            if (CFStringGetCString(if_name, ifn, sizeof(ifn),
                                   kCFStringEncodingASCII)) {
                ifn_p = ifn;
            }
+#endif /* !TARGET_IPHONE_SIMULATOR */
        }
        CFDictionarySetValue(dict, kSCDynamicStorePropNetPrimaryService,
                             primary);
        keyChangeListSetValue(keys, S_state_global_ipv6, dict);
        CFRelease(dict);
 
+#if    !TARGET_IPHONE_SIMULATOR
 #ifdef RTF_IFSCOPE
        if (S_scopedroute_v6) {
            set_ipv6_default_interface(ifn_p);
@@ -3619,9 +4021,11 @@ update_ipv6(CFDictionaryRef      services_info,
            (void)cfstring_to_ip6(val_router, &router);
            set_ipv6_router(&router, ifn_p, is_direct);
        }
+#endif /* !TARGET_IPHONE_SIMULATOR */
     }
     else {
        keyChangeListRemoveValue(keys, S_state_global_ipv6);
+#if    !TARGET_IPHONE_SIMULATOR
 #ifdef RTF_IFSCOPE
        if (S_scopedroute_v6) {
            set_ipv6_default_interface(NULL);
@@ -3630,16 +4034,18 @@ update_ipv6(CFDictionaryRef     services_info,
        { /* route delete default ... */
            set_ipv6_router(NULL, NULL, FALSE);
        }
+#endif /* !TARGET_IPHONE_SIMULATOR */
     }
     return;
 }
 
-static void
+static Boolean
 update_dns(CFDictionaryRef     services_info,
           CFStringRef          primary,
           keyChangeListRef     keys)
 {
-    CFDictionaryRef    dict = NULL;
+    Boolean            changed = FALSE;
+    CFDictionaryRef    dict    = NULL;
 
     if (primary != NULL) {
        CFDictionaryRef service_dict;
@@ -3649,33 +4055,41 @@ update_dns(CFDictionaryRef      services_info,
            dict = CFDictionaryGetValue(service_dict, kSCEntNetDNS);
        }
     }
-    if (dict == NULL) {
+
+    if (!_SC_CFEqual(S_dns_dict, dict)) {
+       if (dict == NULL) {
 #if    !TARGET_OS_IPHONE
-       empty_dns();
+           empty_dns();
 #endif /* !TARGET_OS_IPHONE */
-       keyChangeListRemoveValue(keys, S_state_global_dns);
-    }
-    else {
-       CFMutableDictionaryRef  new_dict;
+           keyChangeListRemoveValue(keys, S_state_global_dns);
+       } else {
+           CFMutableDictionaryRef      new_dict;
 
 #if    !TARGET_OS_IPHONE
-       set_dns(CFDictionaryGetValue(dict, kSCPropNetDNSSearchDomains),
-               CFDictionaryGetValue(dict, kSCPropNetDNSDomainName),
-               CFDictionaryGetValue(dict, kSCPropNetDNSServerAddresses),
-               CFDictionaryGetValue(dict, kSCPropNetDNSSortList));
+           set_dns(CFDictionaryGetValue(dict, kSCPropNetDNSSearchDomains),
+                   CFDictionaryGetValue(dict, kSCPropNetDNSDomainName),
+                   CFDictionaryGetValue(dict, kSCPropNetDNSServerAddresses),
+                   CFDictionaryGetValue(dict, kSCPropNetDNSSortList));
 #endif /* !TARGET_OS_IPHONE */
-       new_dict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
-       CFDictionaryRemoveValue(new_dict, kSCPropInterfaceName);
-       CFDictionaryRemoveValue(new_dict, kSCPropNetDNSSupplementalMatchDomains);
-       CFDictionaryRemoveValue(new_dict, kSCPropNetDNSSupplementalMatchOrders);
-       CFDictionaryRemoveValue(new_dict, DNS_CONFIGURATION_SCOPED_QUERY_KEY);
-       keyChangeListSetValue(keys, S_state_global_dns, new_dict);
-       CFRelease(new_dict);
+           new_dict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
+           CFDictionaryRemoveValue(new_dict, kSCPropInterfaceName);
+           CFDictionaryRemoveValue(new_dict, kSCPropNetDNSSupplementalMatchDomains);
+           CFDictionaryRemoveValue(new_dict, kSCPropNetDNSSupplementalMatchOrders);
+           CFDictionaryRemoveValue(new_dict, DNS_CONFIGURATION_SCOPED_QUERY_KEY);
+           keyChangeListSetValue(keys, S_state_global_dns, new_dict);
+           CFRelease(new_dict);
+       }
+       changed = TRUE;
     }
-    return;
+
+    if (dict != NULL) CFRetain(dict);
+    if (S_dns_dict != NULL) CFRelease(S_dns_dict);
+    S_dns_dict = dict;
+
+    return changed;
 }
 
-static void
+static Boolean
 update_dnsinfo(CFDictionaryRef services_info,
               CFStringRef      primary,
               keyChangeListRef keys,
@@ -3706,15 +4120,42 @@ update_dnsinfo(CFDictionaryRef  services_info,
     if (changed) {
        keyChangeListNotifyKey(keys, S_state_global_dns);
     }
-    return;
+    return changed;
 }
 
-static void
+static Boolean
+update_nwi(nwi_state_t state)
+{
+    unsigned char              signature[CC_SHA1_DIGEST_LENGTH];
+    static unsigned char       signature_last[CC_SHA1_DIGEST_LENGTH];
+
+    _nwi_state_signature(state, signature, sizeof(signature));
+    if (bcmp(signature, signature_last, sizeof(signature)) == 0) {
+       return FALSE;
+    }
+
+    // save [new] signature
+    bcopy(signature, signature_last, sizeof(signature));
+
+    // save [new] configuration
+    if ((S_IPMonitor_debug & kDebugFlag1) != 0) {
+       my_log(LOG_DEBUG, "Updating network information");
+       S_nwi_state_dump(state);
+    }
+    if (_nwi_state_store(state) == FALSE) {
+       my_log(LOG_ERR, "Notifying nwi_state_store failed");
+    }
+
+    return TRUE;
+}
+
+static Boolean
 update_proxies(CFDictionaryRef services_info,
               CFStringRef      primary,
               keyChangeListRef keys,
               CFArrayRef       service_order)
 {
+    Boolean        changed     = FALSE;
     CFDictionaryRef dict       = NULL;
     CFDictionaryRef new_dict;
 
@@ -3729,23 +4170,30 @@ update_proxies(CFDictionaryRef  services_info,
 
     new_dict = proxy_configuration_update(dict,
                                          S_service_state_dict,
-                                         service_order);
-    if (new_dict == NULL) {
-       keyChangeListRemoveValue(keys, S_state_global_proxies);
-    }
-    else {
-       keyChangeListSetValue(keys, S_state_global_proxies, new_dict);
-       CFRelease(new_dict);
+                                         service_order,
+                                         services_info);
+    if (!_SC_CFEqual(S_proxies_dict, new_dict)) {
+       if (new_dict == NULL) {
+           keyChangeListRemoveValue(keys, S_state_global_proxies);
+       } else {
+           keyChangeListSetValue(keys, S_state_global_proxies, new_dict);
+       }
+       changed = TRUE;
     }
-    return;
+
+    if (S_proxies_dict != NULL) CFRelease(S_proxies_dict);
+    S_proxies_dict = new_dict;
+
+    return changed;
 }
 
 #if    !TARGET_OS_IPHONE
-static void
+static Boolean
 update_smb(CFDictionaryRef     services_info,
           CFStringRef          primary,
           keyChangeListRef     keys)
 {
+    Boolean            changed = FALSE;
     CFDictionaryRef    dict    = NULL;
 
     if (primary != NULL) {
@@ -3756,14 +4204,21 @@ update_smb(CFDictionaryRef      services_info,
            dict = CFDictionaryGetValue(service_dict, kSCEntNetSMB);
        }
     }
-    if (dict == NULL) {
-       keyChangeListRemoveValue(keys, S_state_global_smb);
-    }
-    else {
-       keyChangeListSetValue(keys, S_state_global_smb, dict);
+
+    if (!_SC_CFEqual(S_smb_dict, dict)) {
+       if (dict == NULL) {
+           keyChangeListRemoveValue(keys, S_state_global_smb);
+       } else {
+           keyChangeListSetValue(keys, S_state_global_smb, dict);
+       }
+       changed = TRUE;
     }
 
-    return;
+    if (dict != NULL) CFRetain(dict);
+    if (S_smb_dict != NULL) CFRelease(S_smb_dict);
+    S_smb_dict = dict;
+
+    return changed;
 }
 #endif /* !TARGET_OS_IPHONE */
 
@@ -3830,371 +4285,930 @@ rank_dict_set_service_rank(CFMutableDictionaryRef rank_dict,
     return;
 }
 
-typedef struct election_info {
-    int                        n_services;
-    CFArrayRef         order;
-    int                        n_order;
-    CFStringRef                serviceID;
-    CFDictionaryRef    service_dict;
-    Rank               rank;
-} election_info_t;
+static const CFStringRef *transientInterfaceEntityNames[] = {
+    &kSCEntNetPPP,
+};
 
-typedef boolean_t election_func_t(void * context, election_info_t * info);
 
-/*
- * Function: elect_ipv4
- * Purpose:
- *   This function builds the list of IPv4 routes that should be active.
- *   As elect_new_primary() invokes us with each service, we build up the
- *   result in the passed in context, a pointer to an IPv4RouteListRef.
- */
-static boolean_t
-elect_ipv4(void * context, election_info_t * info)
+static void
+CollectTransientServices(const void * key,
+                        const void * value,
+                        void * context)
 {
-    Rank               primary_rank;
-    IPv4RouteListRef * routes_p = (IPv4RouteListRef *)context;
-    IPv4RouteListRef   service_routes;
+    int                        i;
+    CFStringRef                service = key;
+    CFMutableArrayRef  vif_setup_keys = context;
 
-    service_routes = service_dict_get_ipv4_routelist(info->service_dict);
+    /* This service is either a vpn type service or a comm center service */
+    if (!CFStringHasPrefix(service, kSCDynamicStoreDomainSetup)) {
+       return;
+    }
 
-    info->rank = get_service_rank(info->order, info->n_order,
-                                   info->serviceID);
+    for (i = 0; i < sizeof(transientInterfaceEntityNames)/sizeof(transientInterfaceEntityNames[0]); i++) {
+       if (!CFStringHasSuffix(service, *transientInterfaceEntityNames[i])) {
+           continue;
+       }
 
-    if (service_routes == NULL) {
-       return (FALSE);
+       CFArrayAppendValue(vif_setup_keys, service);
     }
+    return;
+}
 
-    primary_rank = RANK_ASSERTION_MASK(service_routes->list->rank);
 
-    if (S_ppp_override_primary
-            && (strncmp(PPP_PREFIX, service_routes->list->ifname,
-                        sizeof(PPP_PREFIX) - 1) == 0)) {
-       /* PPP override: make ppp* look the best */
-       /* Hack: should use interface type, not interface name */
-       primary_rank = kRankAssertionFirst;
+static SCNetworkReachabilityFlags
+GetReachabilityFlagsFromVPN(CFDictionaryRef services_info,
+                           CFStringRef     service_id,
+                           CFStringRef     entity,
+                           CFStringRef     vpn_setup_key)
+{
+    CFStringRef                        key;
+    CFDictionaryRef            dict;
+    SCNetworkReachabilityFlags flags = 0;
+
+
+    key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+                                                       kSCDynamicStoreDomainSetup,
+                                                       service_id,
+                                                       kSCEntNetInterface);
+    dict = CFDictionaryGetValue(services_info, key);
+    CFRelease(key);
+
+    if (isA_CFDictionary(dict)
+       && CFDictionaryContainsKey(dict, kSCPropNetInterfaceDeviceName)) {
+
+       flags = (kSCNetworkReachabilityFlagsReachable
+               | kSCNetworkReachabilityFlagsTransientConnection
+               | kSCNetworkReachabilityFlagsConnectionRequired);
+
+       if (CFEqual(entity, kSCEntNetPPP)) {
+           CFNumberRef num;
+           CFDictionaryRef p_dict = CFDictionaryGetValue(services_info, vpn_setup_key);
+
+           if (!isA_CFDictionary(p_dict)) {
+               return (flags);
+           }
+
+           // get PPP dial-on-traffic status
+           num = CFDictionaryGetValue(p_dict, kSCPropNetPPPDialOnDemand);
+           if (isA_CFNumber(num)) {
+               int32_t ppp_demand;
+
+               if (CFNumberGetValue(num, kCFNumberSInt32Type, &ppp_demand)) {
+                   if (ppp_demand) {
+                       flags |= kSCNetworkReachabilityFlagsConnectionOnTraffic;
+                   }
+               }
+           }
+       }
     }
+    return (flags);
+}
+
+static Boolean
+S_dict_get_boolean(CFDictionaryRef dict, CFStringRef key, Boolean def_value)
+{
+    Boolean            ret = def_value;
 
-    info->rank = RankMake(info->rank, primary_rank);
+    if (dict != NULL) {
+       CFBooleanRef    val;
 
-    if (routes_p != NULL) {
-       *routes_p = IPv4RouteListAddRouteList(*routes_p,
-                                             info->n_services * 3,
-                                             service_routes,
-                                             info->rank);
+       val = CFDictionaryGetValue(dict, key);
+       if (isA_CFBoolean(val) != NULL) {
+           ret = CFBooleanGetValue(val);
+       }
     }
+    return (ret);
+}
 
-    if (primary_rank == kRankAssertionNever) {
-       /* never elect as primary */
-       return (FALSE);
+
+static void
+GetReachabilityFlagsFromTransientServices(CFDictionaryRef services_info,
+                                         SCNetworkReachabilityFlags *reach_flags_v4,
+                                         SCNetworkReachabilityFlags *reach_flags_v6)
+{
+    int i;
+    int count;
+    CFMutableArrayRef vif_setup_keys;
+
+    vif_setup_keys = CFArrayCreateMutable(NULL,
+                                         0,
+                                         &kCFTypeArrayCallBacks);
+
+    CFDictionaryApplyFunction(services_info, CollectTransientServices, vif_setup_keys);
+
+    count = CFArrayGetCount(vif_setup_keys);
+
+    if (count != 0) {
+       my_log(LOG_DEBUG, "Collected the following VIF Setup Keys: %@", vif_setup_keys);
     }
-    if (strncmp(service_routes->list->ifname, "lo0",
-               sizeof(service_routes->list->ifname)) == 0) {
-       /* never elect as primary */
-       return (FALSE);
+
+    for (i = 0; i < count; i++) {
+       CFArrayRef          components = NULL;
+       CFStringRef         entity;
+       CFStringRef         service_id;
+       CFStringRef         vif_setup_key;
+
+       vif_setup_key = CFArrayGetValueAtIndex(vif_setup_keys, i);
+
+       /*
+        * setup key in the following format:
+        * Setup:/Network/Service/<Service ID>/<Entity>
+        */
+       components = CFStringCreateArrayBySeparatingStrings(NULL, vif_setup_key, CFSTR("/"));
+
+       if (CFArrayGetCount(components) != 5) {
+           my_log(LOG_ERR, "Invalid Setup Key encountered: %@", vif_setup_key);
+           goto skip;
+       }
+
+       /* service id is the 3rd element */
+       service_id = CFArrayGetValueAtIndex(components, 3);
+
+       /* entity id is the 4th element */
+       entity = CFArrayGetValueAtIndex(components, 4);
+
+       my_log(LOG_DEBUG, "Service %@ is a %@ Entity", service_id, entity);
+
+
+       if (CFEqual(entity, kSCEntNetPPP)) {
+           SCNetworkReachabilityFlags  flags;
+           CFStringRef                 key;
+
+           flags = GetReachabilityFlagsFromVPN(services_info,
+                                               service_id,
+                                               entity,
+                                               vif_setup_key);
+
+           /* Check for the v4 reachability flags */
+           key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+                                                             kSCDynamicStoreDomainSetup,
+                                                             service_id,
+                                                             kSCEntNetIPv4);
+
+           if (CFDictionaryContainsKey(services_info, key)) {
+               *reach_flags_v4 |= flags;
+               my_log(LOG_DEBUG,"Service %@ setting ipv4 reach flags: %d", service_id, *reach_flags_v4);
+           }
+
+           CFRelease(key);
+
+           /* Check for the v6 reachability flags */
+           key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+                                                             kSCDynamicStoreDomainSetup,
+                                                             service_id,
+                                                             kSCEntNetIPv6);
+
+           if (CFDictionaryContainsKey(services_info, key)) {
+               *reach_flags_v6 |= flags;
+               my_log(LOG_DEBUG,"Service %@ setting ipv6 reach flags: %d", service_id, *reach_flags_v6);
+           }
+           CFRelease(key);
+
+           if (flags != 0) {
+               if (components != NULL) {
+                   CFRelease(components);
+               }
+               goto done;
+           }
+       }
+skip:
+       if (components != NULL) {
+           CFRelease(components);
+       }
     }
+done:
+    CFRelease(vif_setup_keys);
+    return;
+}
 
-    rank_dict_set_service_rank(S_ipv4_service_rank_dict,
-                              info->serviceID, info->rank);
-    return (TRUE);
+static SCNetworkReachabilityFlags
+GetReachFlagsFromStatus(CFStringRef entity, int status)
+{
+    SCNetworkReachabilityFlags flags = 0;
+
+    if (CFEqual(entity, kSCEntNetPPP)) {
+       switch (status) {
+           case PPP_RUNNING :
+               /* if we're really UP and RUNNING */
+               break;
+           case PPP_ONHOLD :
+               /* if we're effectively UP and RUNNING */
+               break;
+           case PPP_IDLE :
+               /* if we're not connected at all */
+               my_log(LOG_INFO, "PPP link idle");
+               flags |= kSCNetworkReachabilityFlagsConnectionRequired;
+               break;
+           case PPP_STATERESERVED :
+               // if we're not connected at all
+               my_log(LOG_INFO, "PPP link idle, dial-on-traffic to connect");
+               flags |= kSCNetworkReachabilityFlagsConnectionRequired;
+               break;
+           default :
+               /* if we're in the process of [dis]connecting */
+               my_log(LOG_INFO, "PPP link, connection in progress");
+               flags |= kSCNetworkReachabilityFlagsConnectionRequired;
+               break;
+       }
+    }
+#ifdef HAVE_IPSEC_STATUS
+    else if (CFEqual(entity, kSCEntNetIPSec)) {
+       switch (status) {
+           case IPSEC_RUNNING :
+               /* if we're really UP and RUNNING */
+               break;
+           case IPSEC_IDLE :
+               /* if we're not connected at all */
+               my_log(LOG_INFO, "IPSec link idle");
+               flags |= kSCNetworkReachabilityFlagsConnectionRequired;
+               break;
+           default :
+               /* if we're in the process of [dis]connecting */
+               my_log(LOG_INFO, "IPSec link, connection in progress");
+               flags |= kSCNetworkReachabilityFlagsConnectionRequired;
+               break;
+       }
+    }
+#endif // HAVE_IPSEC_STATUS
+#ifdef HAVE_VPN_STATUS
+    else if  (CFEqual(entity, kSCEntNetVPN)) {
+       switch (status) {
+           case VPN_RUNNING :
+               /* if we're really UP and RUNNING */
+               break;
+           case VPN_IDLE :
+           case VPN_LOADING :
+           case VPN_LOADED :
+           case VPN_UNLOADING :
+               /* if we're not connected at all */
+               my_log(LOG_INFO, "%s  VPN link idle");
+               flags |= kSCNetworkReachabilityFlagsConnectionRequired;
+               break;
+           default :
+               /* if we're in the process of [dis]connecting */
+               my_log(LOG_INFO, "VPN link, connection in progress");
+               flags |= kSCNetworkReachabilityFlagsConnectionRequired;
+               break;
+       }
+    }
+#endif // HAVE_VPN_STATUS
+    return (flags);
 }
 
 static void
-IPv6RankedListInsertE(IPv6RankedListRef list, IPv6RankedERef e)
+VPNAttributesGet(CFStringRef               service_id,
+                CFDictionaryRef            services_info,
+                SCNetworkReachabilityFlags *flags,
+                CFStringRef                *server_address,
+                int                        af)
 {
-    int        idx                 = 0;
-    int elems_to_be_moved   = 0;
+    int                                i;
+    CFDictionaryRef            entity_dict;
+    boolean_t                  found = FALSE;
+    CFNumberRef                        num;
+    CFDictionaryRef            p_state = NULL;
+    int                                status = 0;
+
+    /* if the IPv[4/6] exist */
+    entity_dict = service_dict_get(service_id, (af == AF_INET) ? kSCEntNetIPv4 : kSCEntNetIPv6);
+    if (!isA_CFDictionary(entity_dict)) {
+       return;
+    }
 
-    if (list == NULL) return;
+    if (af == AF_INET) {
+       entity_dict = CFDictionaryGetValue(entity_dict, kIPv4DictService);
+       if (!isA_CFDictionary(entity_dict)) {
+           return;
+       }
+    }
 
-    for (idx = 0; idx < list->count; idx++) {
-       if ((e->rank < list->elem[idx].rank)) {
+    for (i = 0; i < sizeof(statusEntityNames)/sizeof(statusEntityNames[0]); i++) {
+       p_state = service_dict_get(service_id, *statusEntityNames[i]);
+       /* ensure that this is a VPN Type service */
+       if (isA_CFDictionary(p_state)) {
+           found = TRUE;
            break;
        }
     }
 
-    if ((S_IPMonitor_debug & kDebugFlag2) != 0) {
-       SCLog(TRUE, LOG_NOTICE,
-             CFSTR("IPv6RankedListInsertE: %s flags 0x%x at index %d with rank %u."),
-             e->ifname, e->flags, idx, e->rank);
+    /* Did we find a vpn type service?  If not, we are done.*/
+    if (!found) {
+       return;
+    }
+
+    *flags |= (kSCNetworkReachabilityFlagsReachable| kSCNetworkReachabilityFlagsTransientConnection);
+
+    /* Get the Server Address */
+    if (server_address != NULL) {
+       *server_address = CFDictionaryGetValue(entity_dict, CFSTR("ServerAddress"));
+       *server_address = isA_CFString(*server_address);
+       if (*server_address != NULL) {
+           CFRetain(*server_address);
+       }
     }
 
-    elems_to_be_moved = list->count - idx;
-    if (elems_to_be_moved > 0) {
-       bcopy((void*) &list->elem[idx], (void*) &list->elem[idx+1],
-             elems_to_be_moved * sizeof(*e));
+    /* get status */
+    if (!CFDictionaryGetValueIfPresent(p_state,
+                                      kSCPropNetVPNStatus,
+                                      (const void **)&num) ||
+       !isA_CFNumber(num) ||
+       !CFNumberGetValue(num, kCFNumberSInt32Type, &status)) {
+       return;
     }
 
-    bcopy((void*) e, (void*) &list->elem[idx], sizeof(*e));
-    list->count++;
+    *flags |= GetReachFlagsFromStatus(*statusEntityNames[i], status);
+
+    if (CFEqual(*statusEntityNames[i], kSCEntNetPPP)) {
+       CFStringRef     key;
+       CFDictionaryRef p_setup;
+       int             ppp_demand;
+
+       key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+                                                         kSCDynamicStoreDomainSetup,
+                                                         service_id,
+                                                         kSCEntNetPPP);
+       p_setup = CFDictionaryGetValue(services_info, key);
+       CFRelease(key);
+
+       /* get dial-on-traffic status */
+       if (isA_CFDictionary(p_setup) &&
+           CFDictionaryGetValueIfPresent(p_setup,
+                                         kSCPropNetPPPDialOnDemand,
+                                         (const void **)&num) &&
+           isA_CFNumber(num) &&
+           CFNumberGetValue(num, kCFNumberSInt32Type, &ppp_demand) &&
+           (ppp_demand != 0)) {
+           *flags |= kSCNetworkReachabilityFlagsConnectionOnTraffic;
+           if (status == PPP_IDLE) {
+               *flags |= kSCNetworkReachabilityFlagsInterventionRequired;
+           }
+       }
+    }
     return;
 }
 
-static boolean_t
-elect_ipv6(void * context, election_info_t * info)
-{
-    CFStringRef                if_name;
-    CFStringRef                primaryRankStr  = NULL;
-    CFDictionaryRef    proto_dict;
-    CFStringRef                router;
-    CFDictionaryRef    service_options;
-    IPv6RankedListRef  list = (IPv6RankedListRef) context;
-    IPv6RankedE                elem;
-    CFDictionaryRef    dns_dict = NULL;
-    Rank               primary_rank = kRankAssertionDefault;
 
-    memset((void *)&elem, 0, sizeof(elem));
+typedef struct ElectionInfo {
+    int                        n_services;
+    CFArrayRef         order;
+    int                        n_order;
+    ElectionResultsRef results;
+} ElectionInfo, * ElectionInfoRef;
+
+typedef CFDictionaryApplierFunction    ElectionFuncRef;
 
-    info->rank = get_service_rank(info->order, info->n_order, info->serviceID);
+static void
+CandidateRelease(CandidateRef candidate)
+{
+    my_CFRelease(&candidate->serviceID);
+    my_CFRelease(&candidate->if_name);
+    my_CFRelease(&candidate->signature);
+    return;
+}
 
-    proto_dict = CFDictionaryGetValue(info->service_dict, kSCEntNetIPv6);
-    if (proto_dict == NULL) {
-       return (FALSE);
+static void
+CandidateCopy(CandidateRef dest, CandidateRef src)
+{
+    *dest = *src;
+    if (dest->serviceID) {
+       CFRetain(dest->serviceID);
     }
-    if_name = CFDictionaryGetValue(proto_dict, kSCPropInterfaceName);
-    if (if_name == NULL) {
-       /* we need an interface name */
-       return (FALSE);
+    if (dest->if_name) {
+       CFRetain(dest->if_name);
     }
-    if (CFEqual(if_name, CFSTR("lo0"))) {
-       /* don't ever elect loopback */
-       return (FALSE);
+    if(dest->signature) {
+       CFRetain(dest->signature);
     }
-    CFStringGetCString(if_name, elem.ifname,
-                      sizeof(elem.ifname),
-                      kCFStringEncodingASCII);
-    router = CFDictionaryGetValue(proto_dict,
-                                 kSCPropNetIPv6Router);
-    if (router == NULL) {
-       /* can't become primary without a router */
-       return (FALSE);
+    return;
+}
+
+static ElectionResultsRef
+ElectionResultsAlloc(int size)
+{
+    ElectionResultsRef results;
+
+    results = (ElectionResultsRef)malloc(ElectionResultsComputeSize(size));
+    results->count = 0;
+    results->size = size;
+    return (results);
+}
+
+static void
+ElectionResultsRelease(ElectionResultsRef results)
+{
+    int                        i;
+    CandidateRef       scan;
+
+    for (i = 0, scan = results->candidates;
+        i < results->count;
+        i++, scan++) {
+       CandidateRelease(scan);
     }
+    free(results);
+    return;
+}
+
+static void
+ElectionResultsLog(int level, ElectionResultsRef results, const char * prefix)
+{
+    int                        i;
+    CandidateRef       scan;
 
-    dns_dict = service_dict_get(info->serviceID, kSCEntNetDNS);
-    if (dns_dict != NULL) {
-       elem.flags |= NWI_IFSTATE_FLAGS_HAS_DNS;
+    if (results == NULL) {
+       my_log(level, "%s: no candidates", prefix);
+       return;
     }
+    my_log(level, "%s: %d candidates", prefix, results->count);
+    for (i = 0, scan = results->candidates;
+        i < results->count;
+        i++, scan++) {
+       my_log(level, "%d. %@ Rank=0x%x serviceID=%@", i, scan->if_name,
+              scan->rank, scan->serviceID);
+    }
+    return;
+}
 
-    service_options = service_dict_get(info->serviceID, kSCEntNetService);
-    if (service_options != NULL) {
-       primaryRankStr = CFDictionaryGetValue(service_options, kSCPropNetServicePrimaryRank);
-       if (primaryRankStr != NULL) {
-           primary_rank = PrimaryRankGetRankAssertion(primaryRankStr);
-       }
-       if (primary_rank == kRankAssertionNever) {
-           elem.flags |= NWI_IFSTATE_FLAGS_NOT_IN_LIST;
-           elem.rank = RankMake(info->rank, primary_rank);
-           IPv6RankedListInsertE(list, &elem);
-           return (FALSE);
+/*
+ * Function: ElectionResultsAddCandidate
+ * Purpose:
+ *   Add the candidate into the election results. Find the insertion point
+ *   by comparing the rank of the candidate with existing entries.
+ */
+static void
+ElectionResultsAddCandidate(ElectionResultsRef results, CandidateRef candidate)
+{
+    int                        i;
+    int                        where;
+
+#define BAD_INDEX      (-1)
+    if (results->count == results->size) {
+       /* this should not happen */
+       my_log(LOG_NOTICE, "can't fit another candidate");
+       return;
+    }
+
+    /* find the insertion point */
+    where = BAD_INDEX;
+    for (i = 0; i < results->count; i++) {
+       CandidateRef    this_candidate = results->candidates + i;
+
+       if (candidate->rank < this_candidate->rank) {
+           where = i;
+           break;
        }
     }
+    /* add it to the end */
+    if (where == BAD_INDEX) {
+       CandidateCopy(results->candidates + results->count, candidate);
+       results->count++;
+       return;
+    }
+    /* slide existing entries over */
+    for (i = results->count; i > where; i--) {
+       results->candidates[i] = results->candidates[i - 1];
+    }
+    /* insert element */
+    CandidateCopy(results->candidates + where, candidate);
+    results->count++;
+    return;
+}
 
-    if (get_override_primary(proto_dict)) {
-       primary_rank = kRankAssertionFirst;
+/*
+ * Function: ElectionResultsCopy
+ * Purpose:
+ *   Visit all of the services and invoke the protocol-specific election
+ *   function.  Return the results of the election.
+ */
+static ElectionResultsRef
+ElectionResultsCopy(ElectionFuncRef elect_func, CFArrayRef order, int n_order)
+{
+    int                        count;
+    ElectionInfo       info;
+
+    count = CFDictionaryGetCount(S_service_state_dict);
+    if (count == 0) {
+       return (NULL);
     }
-    else if (S_ppp_override_primary
-            && CFStringHasPrefix(if_name, CFSTR(PPP_PREFIX))) {
-       /* PPP override: make ppp* look the best */
-       /* Hack: should use interface type, not interface name */
-       primary_rank = kRankAssertionFirst;
+    info.results = ElectionResultsAlloc(count);
+    info.n_services = count;
+    info.order = order;
+    info.n_order = n_order;
+    CFDictionaryApplyFunction(S_service_state_dict, elect_func, (void *)&info);
+    if (info.results->count == 0) {
+       ElectionResultsRelease(info.results);
+       info.results = NULL;
     }
+    return (info.results);
+}
 
-    elem.rank = RankMake(info->rank, primary_rank);
-    info->rank = RankMake(info->rank, primary_rank);
+/*
+ * Function: ElectionResultsCandidateNeedsDemotion
+ * Purpose:
+ *   Check whether the given candidate requires demotion. A candidate
+ *   might need to be demoted if its IPv4 and IPv6 services must be coupled
+ *   but a higher ranked service has IPv4 or IPv6.
+ */
+static Boolean
+ElectionResultsCandidateNeedsDemotion(ElectionResultsRef other_results,
+                                     CandidateRef candidate)
+{
+    CandidateRef       other_candidate;
+    Boolean            ret = FALSE;
 
-    (void)cfstring_to_ip6(router, &elem.iaddr6);
+    if (other_results == NULL
+       || candidate->ip_is_coupled == FALSE
+       || RANK_ASSERTION_MASK(candidate->rank) == kRankAssertionNever) {
+       goto done;
+    }
+    other_candidate = other_results->candidates;
+    if (CFEqual(other_candidate->if_name, candidate->if_name)) {
+       /* they are over the same interface, no need to demote */
+       goto done;
+    }
+    if (CFStringHasPrefix(other_candidate->if_name, CFSTR("stf"))) {
+       /* avoid creating a feedback loop */
+       goto done;
+    }
+    if (RANK_ASSERTION_MASK(other_candidate->rank) == kRankAssertionNever) {
+       /* the other candidate isn't eligible to become primary, ignore */
+       goto done;
+    }
+    if (candidate->rank < other_candidate->rank) {
+       /* we're higher ranked than the other candidate, ignore */
+       goto done;
+    }
+    ret = TRUE;
+
+ done:
+    return (ret);
 
-    IPv6RankedListInsertE(list, &elem);
-    rank_dict_set_service_rank(S_ipv6_service_rank_dict,
-                              info->serviceID, info->rank);
-    return (TRUE);
 }
 
+
 static void
-update_nwi_state_ipv6(nwi_state_t state, IPv6RankedListRef list)
+get_signature_sha1(CFStringRef         signature,
+                  unsigned char        * sha1)
 {
-    int idx;
+    CC_SHA1_CTX            ctx;
+    CFDataRef      signature_data;
 
-    if (state == NULL) {
-       return;
-    }
+    signature_data = CFStringCreateExternalRepresentation(NULL,
+                                                         signature,
+                                                         kCFStringEncodingUTF8,
+                                                         0);
+
+    CC_SHA1_Init(&ctx);
+    CC_SHA1_Update(&ctx,
+                  signature_data,
+                  CFDataGetLength(signature_data));
+    CC_SHA1_Final(sha1, &ctx);
 
-    /* A null list indicates to clear the ifstates */
-    nwi_state_clear(state, AF_INET6);
+    CFRelease(signature_data);
+
+    return;
+}
+
+
+static void
+add_candidate_to_nwi_state(nwi_state_t nwi_state, int af,
+                          CandidateRef candidate, Rank rank)
+{
+    uint64_t           flags = 0;
+    char               ifname[IFNAMSIZ];
+    nwi_ifstate_t      ifstate;
 
-    if (list == NULL) {
+    if (nwi_state == NULL) {
+       /* can't happen */
        return;
     }
+    if (RANK_ASSERTION_MASK(rank) == kRankAssertionNever) {
+       flags |= NWI_IFSTATE_FLAGS_NOT_IN_LIST;
+    }
+    if (service_dict_get(candidate->serviceID, kSCEntNetDNS) != NULL) {
+       flags |= NWI_IFSTATE_FLAGS_HAS_DNS;
+    }
+    CFStringGetCString(candidate->if_name, ifname, sizeof(ifname),
+                      kCFStringEncodingASCII);
+    if ((S_IPMonitor_debug & kDebugFlag2) != 0) {
+       my_log(LOG_DEBUG,
+              "Inserting IPv%c [%s] with flags 0x%x primary_rank 0x%x reach_flags %d",
+              ipvx_char(af), ifname, rank, candidate->reachability_flags);
+    }
+    ifstate = nwi_insert_ifstate(nwi_state, ifname, af, flags, rank,
+                                (void *)&candidate->addr,
+                                (void *)&candidate->vpn_server_addr,
+                                candidate->reachability_flags);
+    if (ifstate != NULL && candidate->signature) {
+       uint8_t     hash[CC_SHA1_DIGEST_LENGTH];
+
+       get_signature_sha1(candidate->signature, hash);
+       nwi_ifstate_set_signature(ifstate, hash);
+    }
+    return;
+}
 
-    for (idx = 0 ; idx < list->count; idx++) {
-       if ((S_IPMonitor_debug & kDebugFlag2) != 0) {
-           char        ntopbuf[INET6_ADDRSTRLEN];
 
-           inet_ntop(AF_INET6, &list->elem[idx].iaddr6, ntopbuf,
-                     sizeof(ntopbuf));
+static void
+add_reachability_flags_to_candidate(CandidateRef candidate, CFDictionaryRef services_info, int af)
+{
+    SCNetworkReachabilityFlags flags = kSCNetworkReachabilityFlagsReachable;
+    CFStringRef                        vpn_server_address = NULL;
 
-           SCLog(TRUE, LOG_NOTICE,
-                 CFSTR("Inserting v6 [%s] into list with flags 0x%x"
-                       " with rank %lu ipv6 addr %s"),
-                       list->elem[idx].ifname, list->elem[idx].flags,
-                       list->elem[idx].rank, ntopbuf);
-       }
+    VPNAttributesGet(candidate->serviceID,
+                    services_info,
+                    &flags,
+                    &vpn_server_address,
+                    af);
 
-       nwi_insert_ifstate(state, list->elem[idx].ifname,
-                          AF_INET6, list->elem[idx].flags,
-                          list->elem[idx].rank,
-                          (void *)&list->elem[idx].iaddr6);
+    candidate->reachability_flags = flags;
+
+    if (vpn_server_address == NULL) {
+       bzero(&candidate->vpn_server_addr, sizeof(candidate->vpn_server_addr));
+    } else {
+       char buf[128];
+       CFStringGetCString(vpn_server_address, buf, sizeof(buf), kCFStringEncodingASCII);
+
+       _SC_string_to_sockaddr(buf,
+                              AF_UNSPEC,
+                              (void *)&candidate->vpn_server_addr,
+                              sizeof(candidate->vpn_server_addr));
+
+       CFRelease(vpn_server_address);
     }
-    nwi_state_set_last(state, AF_INET6);
+    return;
 }
+/*
+ * Function: ElectionResultsCopyPrimary
+ * Purpose:
+ *   Use the results of the current protocol and the other protocol to
+ *   determine which service should become primary.
+ *
+ *   At the same time, generate the nwi_state for the protocol.
+ *
+ *   For IPv4, also generate the IPv4 routing table.
+ */
+static CFStringRef
+ElectionResultsCopyPrimary(ElectionResultsRef results,
+                          ElectionResultsRef other_results,
+                          nwi_state_t nwi_state, int af,
+                          IPv4RouteListRef * ret_routes,
+                          CFDictionaryRef services_info)
+{
+    CFStringRef                primary = NULL;
+    Boolean            primary_is_null = FALSE;
+    IPv4RouteListRef   routes = NULL;
 
-static boolean_t
-interface_has_dns(const void * * values, int values_count,
-                 const char * ifname)
-{
-    boolean_t          has_dns = FALSE;
-    int                        i;
-    CFStringRef                ifname_cf;
+    if (nwi_state != NULL) {
+       nwi_state_clear(nwi_state, af);
+    }
+    if (results != NULL) {
+       CandidateRef    deferred[results->count];
+       int             deferred_count;
+       int             i;
+       CandidateRef    scan;
 
-    ifname_cf = CFStringCreateWithCString(NULL, ifname, kCFStringEncodingASCII);
-    for (i = 0; i < values_count; i++) {
-       CFDictionaryRef         dns_dict;
+       deferred_count = 0;
+       for (i = 0, scan = results->candidates;
+            i < results->count;
+            i++, scan++) {
+           Boolean             is_primary = FALSE;
+           Rank                rank = scan->rank;
+           Boolean             skip = FALSE;
+
+           if (primary == NULL
+               && RANK_ASSERTION_MASK(rank) != kRankAssertionNever) {
+               if (ElectionResultsCandidateNeedsDemotion(other_results,
+                                                         scan)) {
+                   /* demote to RankNever */
+                   my_log(LOG_NOTICE,
+                          "IPv%c over %@ demoted: not primary for IPv%c",
+                          ipvx_char(af), scan->if_name, ipvx_other_char(af));
+                   rank = RankMake(rank, kRankAssertionNever);
+                   deferred[deferred_count++] = scan;
+                   skip = TRUE;
+               }
+               else {
+                   primary = CFRetain(scan->serviceID);
+                   is_primary = TRUE;
+               }
+           }
+           if (af == AF_INET) {
+               /* generate the routing table for IPv4 */
+               CFDictionaryRef         service_dict;
+               IPv4RouteListRef        service_routes;
+
+               service_dict
+                   = service_dict_get(scan->serviceID, kSCEntNetIPv4);
+               service_routes = ipv4_dict_get_routelist(service_dict);
+               if (service_routes != NULL) {
+                   routes = IPv4RouteListAddRouteList(routes,
+                                                      results->count * 3,
+                                                      service_routes,
+                                                      rank);
+                   if (service_routes->exclude_from_nwi) {
+                       skip = TRUE;
+                   }
+               }
+               else {
+                   skip = TRUE;
+               }
+           }
+           else {
+               /* a NULL service must be excluded from nwi */
+               CFDictionaryRef         ipv6_dict;
 
-       dns_dict = CFDictionaryGetValue(values[i], kSCEntNetDNS);
-       if (dns_dict != NULL) {
-           CFStringRef         this_ifname;
+               ipv6_dict = service_dict_get(scan->serviceID, kSCEntNetIPv6);
 
-           this_ifname = CFDictionaryGetValue(dns_dict, kSCPropInterfaceName);
-           if (this_ifname != NULL
-               && CFEqual(this_ifname, ifname_cf)) {
-               has_dns = TRUE;
-               break;
+               if (S_dict_get_boolean(ipv6_dict, kIsNULL, FALSE)) {
+                   skip = TRUE;
+               }
+           }
+           if (skip) {
+               /* if we're skipping the primary, it's NULL */
+               if (is_primary) {
+                   primary_is_null = TRUE;
+               }
+           }
+           else {
+               if (primary_is_null) {
+                   /* everything after the primary must be Never */
+                   rank = RankMake(rank, kRankAssertionNever);
+               }
+               add_reachability_flags_to_candidate(scan, services_info, af);
+               add_candidate_to_nwi_state(nwi_state, af, scan, rank);
            }
        }
+       for (i = 0; i < deferred_count; i++) {
+           CandidateRef        candidate = deferred[i];
+           Rank                rank;
+
+           /* demote to RankNever */
+           rank = RankMake(candidate->rank, kRankAssertionNever);
+           add_reachability_flags_to_candidate(candidate, services_info, af);
+           add_candidate_to_nwi_state(nwi_state, af, candidate, rank);
+       }
+    }
+    if (nwi_state != NULL) {
+       nwi_state_set_last(nwi_state, af);
+    }
+    if (ret_routes != NULL) {
+       *ret_routes = routes;
     }
-    CFRelease(ifname_cf);
-    return (has_dns);
+    else if (routes != NULL) {
+       free(routes);
+    }
+    if (primary_is_null) {
+       my_CFRelease(&primary);
+    }
+    return (primary);
+}
+
+
+static inline
+CFStringRef
+service_dict_get_signature(CFDictionaryRef service_dict)
+{
+    return (CFDictionaryGetValue(service_dict, kStoreKeyNetworkSignature));
 }
 
+
+/*
+ * Function: elect_ipv4
+ * Purpose:
+ *   Evaluate the service and determine what rank the service should have.
+ *   If it's a suitable candidate, add it to the election results.
+ */
 static void
-update_nwi_state_ipv4(nwi_state_t state, IPv4RouteListRef route)
+elect_ipv4(const void * key, const void * value, void * context)
 {
-    int                        idx;
-    IPv4RouteRef       r;
-    const void * *     values;
-    const void *       values_buf[10];
-    int                        values_count;
+    Candidate          candidate;
+    CFStringRef                if_name;
+    ElectionInfoRef    info;
+    Rank               primary_rank;
+    CFDictionaryRef    service_dict = (CFDictionaryRef)value;
+    IPv4RouteListRef   service_routes;
+    CFDictionaryRef    v4_dict;
+    CFDictionaryRef    v4_service_dict;
 
-    if (state == NULL) {
+    service_routes = service_dict_get_ipv4_routelist(service_dict);
+    if (service_routes == NULL) {
+       /* no service routes, no service */
        return;
     }
-    nwi_state_clear(state, AF_INET);
-    if (route == NULL) {
+    if_name = service_dict_get_ipv4_ifname(service_dict);
+    if (if_name == NULL) {
+       /* need an interface name */
        return;
     }
-    values_count = CFDictionaryGetCount(S_service_state_dict);
-    if (values_count == 0) {
+    if (CFEqual(if_name, CFSTR("lo0"))) {
+       /* don't ever elect loopback */
        return;
     }
-    if (values_count <= (sizeof(values_buf) / sizeof(values_buf[0]))) {
-       values = values_buf;
-    }
-    else {
-       values = (const void * *)malloc(sizeof(*values) * values_count);
-    }
-    CFDictionaryGetKeysAndValues(S_service_state_dict,
-                                NULL, (const void * *)values);
-    for (idx = 0, r = route->list; idx < route->count; idx++, r++)  {
-       uint64_t                flags = 0ULL;
-
-       if (r->dest.s_addr != 0) {
-           /* we're done, no more default routes */
-           break;
-       }
-       if (RANK_ASSERTION_MASK(r->rank) == kRankAssertionNever) {
-           flags |= NWI_IFSTATE_FLAGS_NOT_IN_LIST;
-       }
-
-       if (interface_has_dns(values, values_count, r->ifname)) {
-           flags |= NWI_IFSTATE_FLAGS_HAS_DNS;
-       }
-       if ((S_IPMonitor_debug & kDebugFlag2) != 0) {
-           SCLog(TRUE, LOG_NOTICE, CFSTR("Inserting v4 [%s] with flags 0x%x primary_rank %u"),
-                 r->ifname, flags, r->rank);
-       }
-       nwi_insert_ifstate(state, r->ifname, AF_INET, flags, r->rank,
-                          (void *)&r->ifa);
-    }
-    if (values != values_buf) {
-       free(values);
+    info = (ElectionInfoRef)context;
+    bzero(&candidate, sizeof(candidate));
+    candidate.serviceID = (CFStringRef)key;
+    candidate.rank = get_service_rank(info->order, info->n_order,
+                                     candidate.serviceID);
+    primary_rank = RANK_ASSERTION_MASK(service_routes->list->rank);
+    if (S_ppp_override_primary
+       && (strncmp(PPP_PREFIX, service_routes->list->ifname,
+                   sizeof(PPP_PREFIX) - 1) == 0)) {
+       /* PPP override: make ppp* look the best */
+       /* Hack: should use interface type, not interface name */
+       primary_rank = kRankAssertionFirst;
     }
-    nwi_state_set_last(state, AF_INET);
+    candidate.rank = RankMake(candidate.rank, primary_rank);
+    candidate.ip_is_coupled = service_get_ip_is_coupled(candidate.serviceID);
+    candidate.if_name = if_name;
+    candidate.addr.v4 = service_routes->list->ifa;
+    rank_dict_set_service_rank(S_ipv4_service_rank_dict,
+                              candidate.serviceID, candidate.rank);
+    v4_dict = CFDictionaryGetValue(service_dict, kSCEntNetIPv4);
+    v4_service_dict = CFDictionaryGetValue(v4_dict, kIPv4DictService);
+    candidate.signature = service_dict_get_signature(v4_service_dict);
+    ElectionResultsAddCandidate(info->results, &candidate);
     return;
 }
 
+
 /*
- * Function: elect_new_primary
+ * Function: elect_ipv6
  * Purpose:
- *   Walk the list of services, passing each service dictionary to "elect_func".
- *   "elect_func" returns rank information about the service that let us
- *   determine the new primary.
+ *   Evaluate the service and determine what rank the service should have.
+ *   If it's a suitable candidate, add it to the election results.
  */
-static CFStringRef
-elect_new_primary(election_func_t * elect_func, void * context,
-                 CFArrayRef order, int n_order)
+static void
+elect_ipv6(const void * key, const void * value, void * context)
 {
-    int                        count;
-    int                        i;
-    election_info_t    info;
-    void * *           keys;
-#define N_KEYS_VALUES_STATIC   10
-    void *             keys_values_buf[N_KEYS_VALUES_STATIC * 2];
-    CFStringRef                new_primary = NULL;
-    Rank               new_rank = 0;
-    void * *           values;
+    CFArrayRef         addrs;
+    Candidate          candidate;
+    CFStringRef                if_name;
+    ElectionInfoRef    info;
+    Rank               primary_rank = kRankAssertionDefault;
+    CFDictionaryRef    ipv6_dict;
+    CFStringRef                router;
+    CFDictionaryRef    service_dict = (CFDictionaryRef)value;
+    CFDictionaryRef    service_options;
 
-    count = CFDictionaryGetCount(S_service_state_dict);
-    if (count <= N_KEYS_VALUES_STATIC) {
-       keys = keys_values_buf;
+
+    ipv6_dict = CFDictionaryGetValue(service_dict, kSCEntNetIPv6);
+    if (ipv6_dict == NULL) {
+       /* no IPv6 */
+       return;
     }
-    else {
-       keys = (void * *)malloc(sizeof(*keys) * count * 2);
+    if_name = CFDictionaryGetValue(ipv6_dict, kSCPropInterfaceName);
+    if (if_name == NULL) {
+       /* need an interface name */
+       return;
+    }
+    if (CFEqual(if_name, CFSTR("lo0"))) {
+       /* don't ever elect loopback */
+       return;
+    }
+    router = CFDictionaryGetValue(ipv6_dict, kSCPropNetIPv6Router);
+    if (router == NULL) {
+       /* don't care about services without a router */
+       return;
     }
-    values = keys + count;
-    CFDictionaryGetKeysAndValues(S_service_state_dict,
-                                (const void * *)keys,
-                                (const void * *)values);
-
-    info.n_services = count;
-    info.order = order;
-    info.n_order = n_order;
-    new_rank = 0;
-    for (i = 0; i < count; i++) {
-       boolean_t       found_new_primary = FALSE;
-
-       info.serviceID = (CFStringRef)keys[i];
-       info.service_dict = (CFDictionaryRef)values[i];
-       info.rank = kRankAssertionMask;
+    info = (ElectionInfoRef)context;
+    bzero(&candidate, sizeof(candidate));
+    candidate.serviceID = (CFStringRef)key;
+    candidate.if_name = if_name;
+    addrs = CFDictionaryGetValue(ipv6_dict, kSCPropNetIPv6Addresses);
+    (void)cfstring_to_ip6(CFArrayGetValueAtIndex(addrs, 0),
+                         &candidate.addr.v6);
+    candidate.rank = get_service_rank(info->order, info->n_order,
+                                     candidate.serviceID);
+    service_options
+       = service_dict_get(candidate.serviceID, kSCEntNetService);
+    if (service_options != NULL) {
+       CFStringRef     primaryRankStr = NULL;
 
-       if ((*elect_func)(context, &info) == FALSE) {
-           continue;
+       primaryRankStr = CFDictionaryGetValue(service_options,
+                                             kSCPropNetServicePrimaryRank);
+       if (primaryRankStr != NULL) {
+           primary_rank = PrimaryRankGetRankAssertion(primaryRankStr);
        }
-       if (new_primary == NULL
-           || (info.rank < new_rank)) {
-           found_new_primary = TRUE;
+       candidate.ip_is_coupled
+           = CFDictionaryContainsKey(service_options, kIPIsCoupled);
+    }
+    if (primary_rank != kRankAssertionNever) {
+       if (get_override_primary(ipv6_dict)) {
+           primary_rank = kRankAssertionFirst;
        }
-
-       if (found_new_primary) {
-           new_primary = info.serviceID;
-           new_rank = info.rank;
+       else if (S_ppp_override_primary
+                && CFStringHasPrefix(if_name, CFSTR(PPP_PREFIX))) {
+           /* PPP override: make ppp* look the best */
+           /* Hack: should use interface type, not interface name */
+           primary_rank = kRankAssertionFirst;
        }
     }
-    if (new_primary != NULL) {
-       CFRetain(new_primary);
-    }
-    if (keys != keys_values_buf) {
-       free(keys);
-    }
-    return (new_primary);
+    candidate.rank = RankMake(candidate.rank, primary_rank);
+    rank_dict_set_service_rank(S_ipv6_service_rank_dict,
+                              candidate.serviceID, candidate.rank);
+    candidate.signature = service_dict_get_signature(ipv6_dict);
+    ElectionResultsAddCandidate(info->results, &candidate);
+    return;
 }
 
 static uint32_t
@@ -4224,6 +5238,11 @@ service_changed(CFDictionaryRef services_info, CFStringRef serviceID)
            changed |= (1 << i);
        }
     }
+
+    if (get_transient_service_changes(serviceID, services_info)) {
+       changed |= (1 << kEntityTypeVPNStatus);
+    }
+
     return (changed);
 }
 
@@ -4267,27 +5286,27 @@ set_new_primary(CFStringRef * primary_p, CFStringRef new_primary,
     if (new_primary != NULL) {
        if (primary != NULL && CFEqual(new_primary, primary)) {
            if ((S_IPMonitor_debug & kDebugFlag1) != 0) {
-               SCLog(TRUE, LOG_NOTICE,
-                     CFSTR("IPMonitor: %@ is still primary %s"),
-                     new_primary, entity);
+               my_log(LOG_DEBUG,
+                      "IPMonitor: %@ is still primary %s",
+                      new_primary, entity);
            }
        }
        else {
            my_CFRelease(primary_p);
            *primary_p = CFRetain(new_primary);
            if ((S_IPMonitor_debug & kDebugFlag1) != 0) {
-               SCLog(TRUE, LOG_NOTICE,
-                     CFSTR("IPMonitor: %@ is the new primary %s"),
-                     new_primary, entity);
+               my_log(LOG_DEBUG,
+                      "IPMonitor: %@ is the new primary %s",
+                      new_primary, entity);
            }
            changed = TRUE;
        }
     }
     else if (primary != NULL) {
        if ((S_IPMonitor_debug & kDebugFlag1) != 0) {
-           SCLog(TRUE, LOG_NOTICE,
-                 CFSTR("IPMonitor: %@ is no longer primary %s"),
-                 primary, entity);
+           my_log(LOG_DEBUG,
+                  "IPMonitor: %@ is no longer primary %s",
+                  primary, entity);
        }
        my_CFRelease(primary_p);
        changed = TRUE;
@@ -4305,13 +5324,6 @@ rank_service_entity(CFDictionaryRef rank_dict, CFStringRef serviceID,
     return (rank_dict_get_service_rank(rank_dict, serviceID));
 }
 
-static __inline__ unsigned int
-IPv6RankedListComputeSize(int n)
-{
-       return (offsetof(IPv6RankedList, elem[n]));
-
-}
-
 static void
 update_interface_rank(CFDictionaryRef services_info, CFStringRef ifname)
 {
@@ -4362,8 +5374,9 @@ append_serviceIDs_for_interface(CFMutableArrayRef services_changed,
            interface = ipv4_dict_get_ifname(ipv4);
            if (interface != NULL && CFEqual(interface, ifname)) {
                if (S_IPMonitor_debug & kDebugFlag1) {
-                   SCLog(TRUE, LOG_NOTICE, CFSTR("Found ipv4 service %@ on interface %@."),
-                         serviceID, ifname);
+                   my_log(LOG_DEBUG,
+                          "Found ipv4 service %@ on interface %@.",
+                          serviceID, ifname);
                }
 
                my_CFArrayAppendUniqueValue(services_changed, serviceID);
@@ -4379,8 +5392,8 @@ append_serviceIDs_for_interface(CFMutableArrayRef services_changed,
            interface = CFDictionaryGetValue(proto_dict, kSCPropInterfaceName);
            if (interface != NULL && CFEqual(interface, ifname)) {
                if (S_IPMonitor_debug & kDebugFlag1) {
-                   SCLog(TRUE, LOG_NOTICE, CFSTR("Found ipv6 service %@ on interface %@."),
-                         serviceID, ifname);
+                   my_log(LOG_DEBUG, "Found ipv6 service %@ on interface %@.",
+                          serviceID, ifname);
                }
 
                my_CFArrayAppendUniqueValue(services_changed, serviceID);
@@ -4393,31 +5406,7 @@ append_serviceIDs_for_interface(CFMutableArrayRef services_changed,
     }
 }
 
-static const CFStringRef *statusEntityNames[] = {
-    &kSCEntNetIPSec,
-    &kSCEntNetPPP,
-    &kSCEntNetVPN,
-};
-
-static void
-add_status_keys(CFMutableArrayRef patterns)
-{
-    int            i;
-
-    for (i = 0; i < sizeof(statusEntityNames)/sizeof(statusEntityNames[0]); i++) {
-       CFStringRef     pattern;
-
-       pattern = state_service_key(kSCCompAnyRegex, *statusEntityNames[i]);
-       CFArrayAppendValue(patterns, pattern);
-       CFRelease(pattern);
-    }
-
-    return;
-}
-
-static
-inline
-const char *
+static __inline__ const char *
 get_changed_str(CFStringRef serviceID, CFStringRef entity, CFDictionaryRef old_dict)
 {
     CFDictionaryRef new_dict    = NULL;
@@ -4522,7 +5511,7 @@ generate_log_changes(nwi_state_t  changes_state,
            str = "*";      // dnsinfo change w/no change to primary
        }
        CFStringAppendFormat(log_output, NULL, CFSTR(" DNS%s"), str);
-    } else if (S_primary_dns != NULL){
+    } else if (S_primary_dns != NULL) {
        CFStringAppendFormat(log_output, NULL, CFSTR(" DNS"));
     }
 
@@ -4549,11 +5538,161 @@ generate_log_changes(nwi_state_t       changes_state,
     return log_output;
 }
 
+#pragma mark -
+#pragma mark Network changed notification
+
+static dispatch_queue_t
+__network_change_queue()
+{
+    static dispatch_once_t     once;
+    static dispatch_queue_t    q;
+
+    dispatch_once(&once, ^{
+       q = dispatch_queue_create("network change queue", NULL);
+    });
+
+    return q;
+}
+
+// Note: must run on __network_change_queue()
+static void
+post_network_change_when_ready()
+{
+    int                    status;
+
+    if (S_network_change_needed == 0) {
+       return;
+    }
+
+    if (!S_network_change_timeout &&
+       (!S_dnsinfo_synced || !S_nwi_synced)) {
+       // if we [still] need to wait for the DNS configuration
+       // or network information changes to be ack'd
+
+       if ((S_IPMonitor_debug & kDebugFlag1) != 0) {
+           my_log(LOG_DEBUG,
+                  "Defer \"" _SC_NOTIFY_NETWORK_CHANGE "\" (%s, %s)",
+                  S_dnsinfo_synced ? "DNS" : "!DNS",
+                  S_nwi_synced     ? "nwi" : "!nwi");
+       }
+       return;
+    }
+
+    // cancel any running timer
+    if (S_network_change_timer != NULL) {
+       dispatch_source_cancel(S_network_change_timer);
+       dispatch_release(S_network_change_timer);
+       S_network_change_timer = NULL;
+       S_network_change_timeout = FALSE;
+    }
+
+    // set (and log?) the post time
+    if ((S_IPMonitor_debug & kDebugFlag1) != 0) {
+       struct timeval  elapsed;
+       struct timeval  end;
+
+       (void) gettimeofday(&end, NULL);
+       timersub(&end, &S_network_change_start, &elapsed);
+
+#define        QUERY_TIME__FMT "%d.%6.6d"
+#define        QUERY_TIME__DIV 1
+
+       my_log(LOG_DEBUG,
+              "Post \"" _SC_NOTIFY_NETWORK_CHANGE "\" (%s: " QUERY_TIME__FMT ": 0x%x)",
+              S_network_change_timeout ? "timeout" : "delayed",
+              elapsed.tv_sec,
+              elapsed.tv_usec / QUERY_TIME__DIV,
+              S_network_change_needed);
+    }
+
+    if ((S_network_change_needed & NETWORK_CHANGE_NET) != 0) {
+       status = notify_post(_SC_NOTIFY_NETWORK_CHANGE_NWI);
+       if (status != NOTIFY_STATUS_OK) {
+           my_log(LOG_ERR,
+                  "IPMonitor: notify_post(" _SC_NOTIFY_NETWORK_CHANGE_NWI ") failed: error=%ld", status);
+       }
+    }
+
+    if ((S_network_change_needed & NETWORK_CHANGE_DNS) != 0) {
+       status = notify_post(_SC_NOTIFY_NETWORK_CHANGE_DNS);
+       if (status != NOTIFY_STATUS_OK) {
+           my_log(LOG_ERR,
+                  "IPMonitor: notify_post(" _SC_NOTIFY_NETWORK_CHANGE_DNS ") failed: error=%ld", status);
+       }
+    }
+
+    if ((S_network_change_needed & NETWORK_CHANGE_PROXY) != 0) {
+       status = notify_post(_SC_NOTIFY_NETWORK_CHANGE_PROXY);
+       if (status != NOTIFY_STATUS_OK) {
+           my_log(LOG_ERR,
+                  "IPMonitor: notify_post(" _SC_NOTIFY_NETWORK_CHANGE_PROXY ") failed: error=%ld", status);
+       }
+    }
+
+    status = notify_post(_SC_NOTIFY_NETWORK_CHANGE);
+    if (status != NOTIFY_STATUS_OK) {
+       my_log(LOG_ERR,
+              "IPMonitor: notify_post(" _SC_NOTIFY_NETWORK_CHANGE ") failed: error=%ld", status);
+    }
+
+    S_network_change_needed = 0;
+    return;
+}
+
+#define TRAILING_EDGE_TIMEOUT_NSEC     5 * NSEC_PER_SEC    // 5s
+
+// Note: must run on __network_change_queue()
+static void
+post_network_change(uint32_t change)
+{
+    if (S_network_change_needed == 0) {
+       // set the start time
+       (void) gettimeofday(&S_network_change_start, NULL);
+    }
+
+    // indicate that we need to post a change for ...
+    S_network_change_needed |= change;
+
+    // cancel any running timer
+    if (S_network_change_timer != NULL) {
+       dispatch_source_cancel(S_network_change_timer);
+       dispatch_release(S_network_change_timer);
+       S_network_change_timer = NULL;
+       S_network_change_timeout = FALSE;
+    }
+
+    // if needed, start new timer
+    if (!S_dnsinfo_synced || !S_nwi_synced) {
+       S_network_change_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,
+                                                       0,
+                                                       0,
+                                                       __network_change_queue());
+       dispatch_source_set_event_handler(S_network_change_timer, ^{
+           S_network_change_timeout = TRUE;
+           post_network_change_when_ready();
+       });
+       dispatch_source_set_timer(S_network_change_timer,
+                                 dispatch_time(DISPATCH_TIME_NOW,
+                                               TRAILING_EDGE_TIMEOUT_NSEC),    // start
+                                 0,                                            // interval
+                                 10 * NSEC_PER_MSEC);                          // leeway
+       dispatch_resume(S_network_change_timer);
+    }
+
+    post_network_change_when_ready();
+
+    return;
+}
+
+#pragma mark -
+#pragma mark Process network (SCDynamicStore) changes
+
 static void
 IPMonitorNotify(SCDynamicStoreRef session, CFArrayRef changed_keys,
                void * not_used)
 {
     CFIndex            count;
+    uint32_t           changes                 = 0;
     nwi_state_t                changes_state           = NULL;
     boolean_t          dns_changed             = FALSE;
     boolean_t          dnsinfo_changed         = FALSE;
@@ -4563,7 +5702,7 @@ IPMonitorNotify(SCDynamicStoreRef session, CFArrayRef changed_keys,
     CFMutableArrayRef  if_rank_changes         = NULL;
     keyChangeList      keys;
     CFIndex            n;
-    CFStringRef                network_change_msg;
+    CFStringRef                network_change_msg      = NULL;
     int                        n_services;
     int                        n_service_order         = 0;
     nwi_state_t                old_nwi_state           = NULL;
@@ -4573,6 +5712,7 @@ IPMonitorNotify(SCDynamicStoreRef session, CFArrayRef changed_keys,
     CFDictionaryRef    old_primary_smb         = NULL;
 #endif // !TARGET_OS_IPHONE
     boolean_t          proxies_changed         = FALSE;
+    boolean_t          reachability_changed    = FALSE;
     CFArrayRef         service_order;
     CFMutableArrayRef  service_changes         = NULL;
     CFDictionaryRef    services_info           = NULL;
@@ -4586,8 +5726,8 @@ IPMonitorNotify(SCDynamicStoreRef session, CFArrayRef changed_keys,
     }
 
     if ((S_IPMonitor_debug & kDebugFlag1) != 0) {
-       SCLog(TRUE, LOG_NOTICE,
-             CFSTR("IPMonitor: changes %@ (%d)"), changed_keys, count);
+       my_log(LOG_DEBUG,
+              "IPMonitor: changes %@ (%d)", changed_keys, count);
     }
 
     if (S_primary_dns != NULL) {
@@ -4636,32 +5776,43 @@ IPMonitorNotify(SCDynamicStoreRef session, CFArrayRef changed_keys,
 #endif /* !TARGET_OS_IPHONE */
        else if (CFStringHasPrefix(change, S_state_service_prefix)) {
            int         i;
-           boolean_t   status_changed = FALSE;
+           CFStringRef serviceID;
 
            for (i = 0; i < sizeof(statusEntityNames)/sizeof(statusEntityNames[0]); i++) {
                if (CFStringHasSuffix(change, *statusEntityNames[i])) {
-                   status_changed = TRUE;
                    dnsinfo_changed = TRUE;
                    break;
                }
            }
 
-           if (!status_changed) {
-               CFStringRef serviceID = parse_component(change,
-                                                       S_state_service_prefix);
-               if (serviceID) {
-                   my_CFArrayAppendUniqueValue(service_changes, serviceID);
-                   CFRelease(serviceID);
-               }
+           serviceID = parse_component(change, S_state_service_prefix);
+           if (serviceID) {
+               my_CFArrayAppendUniqueValue(service_changes, serviceID);
+               CFRelease(serviceID);
            }
        }
        else if (CFStringHasPrefix(change, S_setup_service_prefix)) {
+           int j;
+
            CFStringRef serviceID = parse_component(change,
                                                    S_setup_service_prefix);
            if (serviceID) {
                my_CFArrayAppendUniqueValue(service_changes, serviceID);
                CFRelease(serviceID);
            }
+
+           for (j = 0; j < sizeof(transientInterfaceEntityNames)/sizeof(transientInterfaceEntityNames[0]); j++) {
+               if (CFStringHasSuffix(change, *transientInterfaceEntityNames[j])) {
+                   reachability_changed = TRUE;
+                   break;
+               }
+           }
+
+           if (CFStringHasSuffix(change, kSCEntNetInterface)) {
+                reachability_changed = TRUE;
+           }
+
+
        }
        else if (CFStringHasSuffix(change, kSCEntNetService)) {
            CFStringRef ifname = my_CFStringCopyComponent(change, CFSTR("/"), 3);
@@ -4684,8 +5835,8 @@ IPMonitorNotify(SCDynamicStoreRef session, CFArrayRef changed_keys,
            CFStringRef ifname = CFArrayGetValueAtIndex(if_rank_changes, i);
 
            if (S_IPMonitor_debug & kDebugFlag1) {
-               SCLog(TRUE, LOG_NOTICE, CFSTR("Interface rank changed %@"),
-                     ifname);
+               my_log(LOG_DEBUG, "Interface rank changed %@",
+                      ifname);
            }
            append_serviceIDs_for_interface(service_changes, ifname);
        }
@@ -4698,8 +5849,8 @@ IPMonitorNotify(SCDynamicStoreRef session, CFArrayRef changed_keys,
     if (service_order != NULL) {
        n_service_order = CFArrayGetCount(service_order);
        if ((S_IPMonitor_debug & kDebugFlag1) != 0) {
-           SCLog(TRUE, LOG_NOTICE,
-                 CFSTR("IPMonitor: service_order %@ "), service_order);
+           my_log(LOG_DEBUG,
+                  "IPMonitor: service_order %@ ", service_order);
        }
     }
 
@@ -4736,7 +5887,7 @@ IPMonitorNotify(SCDynamicStoreRef session, CFArrayRef changed_keys,
        }
        if ((changes & (1 << kEntityTypeDNS)) != 0) {
            if (S_primary_dns != NULL && CFEqual(S_primary_dns, serviceID)) {
-               update_dns(services_info, serviceID, &keys);
+               dns_changed = TRUE;
            }
            dnsinfo_changed = TRUE;
        }
@@ -4746,74 +5897,75 @@ IPMonitorNotify(SCDynamicStoreRef session, CFArrayRef changed_keys,
 #if    !TARGET_OS_IPHONE
        if ((changes & (1 << kEntityTypeSMB)) != 0) {
            if (S_primary_smb != NULL && CFEqual(S_primary_smb, serviceID)) {
-               update_smb(services_info, serviceID, &keys);
+               smb_changed = TRUE;
            }
        }
-#endif /* !TARGET_OS_IPHONE */
+#endif
     }
 
+       if ((changes & (1 <<kEntityTypeVPNStatus)) != 0) {
+           global_ipv4_changed = TRUE;
+           global_ipv6_changed = TRUE;
+       }
+
     /* ensure S_nwi_state can hold as many services as we have currently */
     n_services = CFDictionaryGetCount(S_service_state_dict);
     old_nwi_state = nwi_state_copy_priv(S_nwi_state);
     S_nwi_state = nwi_state_new(S_nwi_state, n_services);
 
-    if (global_ipv4_changed || dnsinfo_changed) {
-       IPv4RouteListRef        new_routelist = NULL;
-       CFStringRef             new_primary;
-
+    if (global_ipv4_changed) {
+       if (S_ipv4_results != NULL) {
+           ElectionResultsRelease(S_ipv4_results);
+       }
+       S_ipv4_results
+           = ElectionResultsCopy(elect_ipv4, service_order, n_service_order);
        if ((S_IPMonitor_debug & kDebugFlag1) != 0) {
-           SCLog(TRUE, LOG_NOTICE,
-                 CFSTR("IPMonitor: IPv4 service election"));
+           ElectionResultsLog(LOG_DEBUG, S_ipv4_results, "IPv4");
        }
-       new_primary = elect_new_primary(&elect_ipv4, &new_routelist,
-                                       service_order, n_service_order);
-       update_nwi_state_ipv4(S_nwi_state, new_routelist);
-
-       if (global_ipv4_changed) {
-           (void)set_new_primary(&S_primary_ipv4, new_primary, "IPv4");
-           update_ipv4(S_primary_ipv4, new_routelist, &keys);
+    }
+    if (global_ipv6_changed) {
+       if (S_ipv6_results != NULL) {
+           ElectionResultsRelease(S_ipv6_results);
        }
-       else if (new_routelist != NULL) {
-           free(new_routelist);
-           new_routelist = NULL;
+       S_ipv6_results
+           = ElectionResultsCopy(elect_ipv6, service_order, n_service_order);
+       if ((S_IPMonitor_debug & kDebugFlag1) != 0) {
+           ElectionResultsLog(LOG_DEBUG, S_ipv6_results, "IPv6");
        }
-       my_CFRelease(&new_primary);
     }
-    if (global_ipv6_changed || dnsinfo_changed) {
-       IPv6RankedListRef       list = NULL;
+    if (global_ipv4_changed || global_ipv6_changed || dnsinfo_changed) {
        CFStringRef             new_primary;
-       int                     size;
-
-       size = (n_services != 0)
-           ? (sizeof(IPv6RankedList)
-              + IPv6RankedListComputeSize(n_services)) : 0;
-
-       if (size != 0) {
-           list = malloc(size);
-       }
-       if (list != NULL) {
-           list->count = 0;
-           list->size = size;
-       }
+       IPv4RouteListRef        new_routelist = NULL;
 
+       /* IPv4 */
        if ((S_IPMonitor_debug & kDebugFlag1) != 0) {
-           SCLog(TRUE, LOG_NOTICE,
-                 CFSTR("IPMonitor: IPv6 service election"));
-       }
-       new_primary = elect_new_primary(&elect_ipv6, list,
-                                       service_order, n_service_order);
-       update_nwi_state_ipv6(S_nwi_state, list);
-
-       if (global_ipv6_changed) {
-           (void)set_new_primary(&S_primary_ipv6, new_primary, "IPv6");
-           update_ipv6(services_info, S_primary_ipv6, &keys);
-       }
+           my_log(LOG_DEBUG,
+                  "IPMonitor: electing IPv4 primary");
+       }
+       new_primary = ElectionResultsCopyPrimary(S_ipv4_results,
+                                                S_ipv6_results,
+                                                S_nwi_state, AF_INET,
+                                                &new_routelist,
+                                                services_info);
+       (void)set_new_primary(&S_primary_ipv4, new_primary, "IPv4");
+       update_ipv4(S_primary_ipv4, new_routelist, &keys);
+       my_CFRelease(&new_primary);
 
-       if (list != NULL) {
-           free(list);
-       }
+       /* IPv6 */
+       if ((S_IPMonitor_debug & kDebugFlag1) != 0) {
+           my_log(LOG_DEBUG,
+                  "IPMonitor: electing IPv6 primary");
+       }
+       new_primary = ElectionResultsCopyPrimary(S_ipv6_results,
+                                                S_ipv4_results,
+                                                S_nwi_state, AF_INET6,
+                                                NULL,
+                                                services_info);
+       (void)set_new_primary(&S_primary_ipv6, new_primary, "IPv6");
+       update_ipv6(S_primary_ipv6, &keys);
        my_CFRelease(&new_primary);
     }
+
     if (global_ipv4_changed || global_ipv6_changed) {
        CFStringRef     new_primary_dns     = NULL;
        CFStringRef     new_primary_proxies = NULL;
@@ -4870,7 +6022,6 @@ IPMonitorNotify(SCDynamicStoreRef session, CFArrayRef changed_keys,
        }
 
        if (set_new_primary(&S_primary_dns, new_primary_dns, "DNS")) {
-           update_dns(services_info, S_primary_dns, &keys);
            dns_changed = TRUE;
            dnsinfo_changed = TRUE;
        }
@@ -4879,62 +6030,122 @@ IPMonitorNotify(SCDynamicStoreRef session, CFArrayRef changed_keys,
        }
 #if    !TARGET_OS_IPHONE
        if (set_new_primary(&S_primary_smb, new_primary_smb, "SMB")) {
-           update_smb(services_info, S_primary_smb, &keys);
            smb_changed = TRUE;
        }
 #endif /* !TARGET_OS_IPHONE */
     }
-    if (dnsinfo_changed || global_ipv4_changed || global_ipv6_changed) {
+
+    if (!proxies_changed && dnsinfo_changed &&
+       ((G_supplemental_proxies_follow_dns != NULL) && CFBooleanGetValue(G_supplemental_proxies_follow_dns))) {
+       proxies_changed = TRUE;
+    }
+
+    changes_state = nwi_state_diff(old_nwi_state, S_nwi_state);
+
+    if (global_ipv4_changed || global_ipv6_changed || dnsinfo_changed || reachability_changed) {
        if (S_nwi_state != NULL) {
            S_nwi_state->generation_count = mach_absolute_time();
-           if ((S_IPMonitor_debug & kDebugFlag1) != 0) {
-               syslog(LOG_NOTICE, "Updating network information");
-               _nwi_state_dump(LOG_NOTICE, S_nwi_state);
-           }
-           if (_nwi_state_store(S_nwi_state) == FALSE) {
-               SCLog(TRUE, LOG_ERR, CFSTR("Notifying nwi_state_store failed"));
+           if (global_ipv4_changed || global_ipv6_changed || reachability_changed) {
+               SCNetworkReachabilityFlags reach_flags_v4 = 0;
+               SCNetworkReachabilityFlags reach_flags_v6 = 0;
+
+               GetReachabilityFlagsFromTransientServices(services_info,
+                                                         &reach_flags_v4,
+                                                         &reach_flags_v6);
+
+               _nwi_state_set_reachability_flags(S_nwi_state, reach_flags_v4, reach_flags_v6);
            }
+
+           /* Update the per-interface generation count */
+           _nwi_state_update_interface_generations(old_nwi_state, S_nwi_state, changes_state);
+       }
+
+       if (update_nwi(S_nwi_state)) {
+           changes |= NETWORK_CHANGE_NET;
+
+           /*
+            * the DNS configuration includes per-resolver configuration
+            * reachability flags that are based on the nwi state.  Let's
+            * make sure that we check for changes
+            */
+           dnsinfo_changed = TRUE;
+       }
+    }
+    if (dns_changed) {
+       if (update_dns(services_info, S_primary_dns, &keys)) {
+           changes |= NETWORK_CHANGE_DNS;
+           dnsinfo_changed = TRUE;
+       } else {
+           dns_changed = FALSE;
        }
     }
     if (dnsinfo_changed) {
-       update_dnsinfo(services_info, S_primary_dns, &keys, service_order);
+       if (update_dnsinfo(services_info, S_primary_dns, &keys, service_order)) {
+           changes |= NETWORK_CHANGE_DNS;
+       } else {
+           dnsinfo_changed = FALSE;
+       }
     }
-    if (proxies_changed ||
-       (dnsinfo_changed && (G_supplemental_proxies_follow_dns != NULL) && CFBooleanGetValue(G_supplemental_proxies_follow_dns))
-       ) {
+    if (proxies_changed) {
        // if proxy change OR supplemental Proxies follow supplemental DNS
-       update_proxies(services_info, S_primary_proxies, &keys, service_order);
-       proxies_changed = TRUE;
+       if (update_proxies(services_info, S_primary_proxies, &keys, service_order)) {
+           changes |= NETWORK_CHANGE_PROXY;
+       } else {
+           proxies_changed = FALSE;
+       }
+    }
+#if    !TARGET_OS_IPHONE
+    if (smb_changed) {
+       if (update_smb(services_info, S_primary_smb, &keys)) {
+           changes |= NETWORK_CHANGE_SMB;
+       } else {
+           smb_changed = FALSE;
+       }
     }
+#endif /* !TARGET_OS_IPHONE */
     my_CFRelease(&service_changes);
     my_CFRelease(&services_info);
     my_CFRelease(&if_rank_changes);
-    changes_state = nwi_state_diff(old_nwi_state, S_nwi_state);
-    if ((S_IPMonitor_debug & kDebugFlag2) != 0) {
-       syslog(LOG_NOTICE, "network information diffs: ");
-       _nwi_state_dump(LOG_NOTICE, changes_state);
-    }
-    network_change_msg =
-       generate_log_changes(changes_state,
-                            dns_changed,
-                            dnsinfo_changed,
-                            old_primary_dns,
-                            proxies_changed,
-                            old_primary_proxy,
+
+    if (changes != 0) {
+       network_change_msg =
+           generate_log_changes(changes_state,
+                                dns_changed,
+                                dnsinfo_changed,
+                                old_primary_dns,
+                                proxies_changed,
+                                old_primary_proxy,
 #if    !TARGET_OS_IPHONE
-                            smb_changed,
-                            old_primary_smb
+                                smb_changed,
+                                old_primary_smb
 #else  // !TARGET_OS_IPHONE
-                            FALSE,
-                            NULL
+                                FALSE,         // smb_changed
+                                NULL           // old_primary_smb
 #endif // !TARGET_OS_IPHONE
-                            );
-    keyChangeListApplyToStore(&keys, session, network_change_msg);
+                                );
+    }
+
+    keyChangeListApplyToStore(&keys, session);
     my_CFRelease(&old_primary_dns);
     my_CFRelease(&old_primary_proxy);
 #if    !TARGET_OS_IPHONE
     my_CFRelease(&old_primary_smb);
 #endif // !TARGET_OS_IPHONE
+
+    if (changes != 0) {
+       dispatch_async(__network_change_queue(), ^{
+           post_network_change(changes);
+       });
+    }
+
+    if ((network_change_msg != NULL) && (CFStringGetLength(network_change_msg) != 0)) {
+       my_log(LOG_NOTICE, "network changed:%@", network_change_msg);
+    } else if (keyChangeListActive(&keys)) {
+       my_log(LOG_NOTICE, "network changed.");
+    } else {
+       my_log(LOG_DEBUG, "network event w/no changes");
+    }
+
     my_CFRelease(&network_change_msg);
 
     if (changes_state != NULL) {
@@ -4947,6 +6158,78 @@ IPMonitorNotify(SCDynamicStoreRef session, CFArrayRef changed_keys,
     return;
 }
 
+static void
+watch_proxies()
+{
+#if    !TARGET_OS_IPHONE
+    const _scprefs_observer_type type = scprefs_observer_type_mcx;
+#else
+    const _scprefs_observer_type type = scprefs_observer_type_global;
+#endif
+    static dispatch_queue_t proxy_cb_queue;
+
+    proxy_cb_queue = dispatch_queue_create("com.apple.SystemConfiguration.IPMonitor.proxy", NULL);
+    _scprefs_observer_watch(type,
+                            "com.apple.SystemConfiguration.plist",
+                            proxy_cb_queue,
+                            ^{
+                                SCDynamicStoreNotifyValue(NULL, S_state_global_proxies);
+                                notify_post(_SC_NOTIFY_NETWORK_CHANGE_PROXY);
+                                my_log(LOG_DEBUG, "IPMonitor: Notifying:\n%@",
+                                       S_state_global_proxies);
+                            });
+    return;
+}
+
+#if    ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 60000))
+#include "IPMonitorControlPrefs.h"
+
+__private_extern__ SCLoggerRef
+my_log_get_logger()
+{
+    return (S_IPMonitor_logger);
+}
+
+static void
+prefs_changed(__unused SCPreferencesRef prefs)
+{
+    if (S_bundle_logging_verbose || IPMonitorControlPrefsIsVerbose()) {
+       S_IPMonitor_debug = kDebugFlagDefault;
+       S_IPMonitor_verbose = TRUE;
+       SCLoggerSetFlags(S_IPMonitor_logger, kSCLoggerFlagsFile | kSCLoggerFlagsDefault);
+       my_log(LOG_DEBUG, "IPMonitor: Setting logging verbose mode on.");
+    } else {
+       my_log(LOG_DEBUG, "IPMonitor: Setting logging verbose mode off.");
+       S_IPMonitor_debug = 0;
+       S_IPMonitor_verbose = FALSE;
+       SCLoggerSetFlags(S_IPMonitor_logger, kSCLoggerFlagsDefault);
+    }
+    return;
+}
+
+#define LOGGER_ID CFSTR("com.apple.networking.IPMonitor")
+static void
+my_log_init()
+{
+    if (S_IPMonitor_logger != NULL) {
+       return;
+    }
+    S_IPMonitor_logger = SCLoggerCreate(LOGGER_ID);
+    return;
+
+}
+
+#else  // ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 60000))
+
+static void
+my_log_init()
+{
+    return;
+}
+
+#endif // ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 60000))
+
+
 static void
 ip_plugin_init()
 {
@@ -4972,9 +6255,9 @@ ip_plugin_init()
     S_session = SCDynamicStoreCreate(NULL, CFSTR("IPMonitor"),
                                   IPMonitorNotify, NULL);
     if (S_session == NULL) {
-       SCLog(TRUE, LOG_ERR,
-             CFSTR("IPMonitor ip_plugin_init SCDynamicStoreCreate failed: %s"),
-             SCErrorString(SCError()));
+       my_log(LOG_ERR,
+              "IPMonitor ip_plugin_init SCDynamicStoreCreate failed: %s",
+              SCErrorString(SCError()));
        return;
     }
     S_state_global_ipv4
@@ -5034,8 +6317,20 @@ ip_plugin_init()
     /* register for State: and Setup: per-service notifications */
     add_service_keys(kSCCompAnyRegex, keys, patterns);
 
+    pattern = setup_service_key(kSCCompAnyRegex, kSCEntNetPPP);
+    CFArrayAppendValue(patterns, pattern);
+    CFRelease(pattern);
+
+    pattern = setup_service_key(kSCCompAnyRegex, kSCEntNetVPN);
+    CFArrayAppendValue(patterns, pattern);
+    CFRelease(pattern);
+
+    pattern = setup_service_key(kSCCompAnyRegex, kSCEntNetInterface);
+    CFArrayAppendValue(patterns, pattern);
+    CFRelease(pattern);
+
     /* register for State: per-service PPP/VPN/IPSec status notifications */
-    add_status_keys(patterns);
+    add_status_keys(kSCCompAnyRegex, patterns);
 
     /* register for interface rank notifications */
     pattern = if_rank_key_copy(kSCCompAnyRegex);
@@ -5060,19 +6355,19 @@ ip_plugin_init()
     CFArrayAppendValue(keys, S_private_resolvers);
 
     if (!SCDynamicStoreSetNotificationKeys(S_session, keys, patterns)) {
-       SCLog(TRUE, LOG_ERR,
-             CFSTR("IPMonitor ip_plugin_init "
-                   "SCDynamicStoreSetNotificationKeys failed: %s"),
+       my_log(LOG_ERR,
+              "IPMonitor ip_plugin_init "
+              "SCDynamicStoreSetNotificationKeys failed: %s",
              SCErrorString(SCError()));
        goto done;
     }
 
     rls = SCDynamicStoreCreateRunLoopSource(NULL, S_session, 0);
     if (rls == NULL) {
-       SCLog(TRUE, LOG_ERR,
-             CFSTR("IPMonitor ip_plugin_init "
-                   "SCDynamicStoreCreateRunLoopSource failed: %s"),
-             SCErrorString(SCError()));
+       my_log(LOG_ERR,
+              "IPMonitor ip_plugin_init "
+              "SCDynamicStoreCreateRunLoopSource failed: %s",
+              SCErrorString(SCError()));
        goto done;
     }
 
@@ -5092,6 +6387,7 @@ ip_plugin_init()
 #endif /* !TARGET_OS_IPHONE */
 
     if_rank_dict_init();
+    watch_proxies();
 
   done:
     my_CFRelease(&keys);
@@ -5129,6 +6425,7 @@ load_IPMonitor(CFBundleRef bundle, Boolean bundleVerbose)
     CFDictionaryRef    info_dict;
 
     info_dict = CFBundleGetInfoDictionary(bundle);
+
     if (info_dict != NULL) {
        S_append_state
            = S_get_plist_boolean(info_dict,
@@ -5137,10 +6434,51 @@ load_IPMonitor(CFBundleRef bundle, Boolean bundleVerbose)
     }
     if (bundleVerbose) {
        S_IPMonitor_debug = kDebugFlagDefault;
-    }
+       S_bundle_logging_verbose = bundleVerbose;
+       S_IPMonitor_verbose = TRUE;
+    }
+
+    my_log_init();
+
+#if ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 60000))
+    /* register to receive changes to verbose and read the initial setting  */
+    IPMonitorControlPrefsInit(CFRunLoopGetCurrent(), prefs_changed);
+    prefs_changed(NULL);
+
+#endif // ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 60000))
+
+    load_DNSConfiguration(bundle,                      // bundle
+                         S_IPMonitor_logger,           // SCLogger
+                         &S_IPMonitor_verbose,         // bundleVerbose
+                         ^(Boolean inSync) {           // syncHandler
+                             dispatch_async(__network_change_queue(), ^{
+                                 S_dnsinfo_synced = inSync;
+
+                                 if (inSync &&
+                                     ((S_network_change_needed & NETWORK_CHANGE_DNS) == 0)) {
+                                     // all of the mDNSResponder ack's should result
+                                     // in a [new] network change being posted
+                                     post_network_change(NETWORK_CHANGE_DNS);
+                                 } else {
+                                     post_network_change_when_ready();
+                                 }
+                             });
+                         });
+
+    load_NetworkInformation(bundle,                    // bundle
+                           S_IPMonitor_logger,         // SCLogger
+                           &S_IPMonitor_verbose,       // bundleVerbose
+                           ^(Boolean inSync) {         // syncHandler
+                               dispatch_async(__network_change_queue(), ^{
+                                   S_nwi_synced = inSync;
+                                   post_network_change_when_ready();
+                               });
+                           });
 
     dns_configuration_init(bundle);
+
     proxy_configuration_init(bundle);
+
     ip_plugin_init();
 
 #if    !TARGET_OS_IPHONE
@@ -5149,7 +6487,10 @@ load_IPMonitor(CFBundleRef bundle, Boolean bundleVerbose)
     }
 #endif /* !TARGET_OS_IPHONE */
 
+#if    !TARGET_IPHONE_SIMULATOR
     load_hostname((S_IPMonitor_debug & kDebugFlag1) != 0);
+#endif /* !TARGET_IPHONE_SIMULATOR */
+
 #if    !TARGET_OS_IPHONE
     load_smb_configuration((S_IPMonitor_debug & kDebugFlag1) != 0);
 #endif /* !TARGET_OS_IPHONE */
@@ -5163,8 +6504,12 @@ load_IPMonitor(CFBundleRef bundle, Boolean bundleVerbose)
 
 
 #ifdef TEST_IPMONITOR
+
 #include "dns-configuration.c"
+
+#if    !TARGET_IPHONE_SIMULATOR
 #include "set-hostname.c"
+#endif /* !TARGET_IPHONE_SIMULATOR */
 
 int
 main(int argc, char **argv)
@@ -5178,6 +6523,7 @@ main(int argc, char **argv)
 
     load_IPMonitor(CFBundleGetMainBundle(), FALSE);
     prime_IPMonitor();
+    S_IPMonitor_debug = kDebugFlag1;
     CFRunLoopRun();
     /* not reached */
     exit(0);
@@ -5186,8 +6532,12 @@ main(int argc, char **argv)
 #endif /* TEST_IPMONITOR */
 
 #ifdef TEST_IPV4_ROUTELIST
+
 #include "dns-configuration.c"
+
+#if    !TARGET_IPHONE_SIMULATOR
 #include "set-hostname.c"
+#endif /* !TARGET_IPHONE_SIMULATOR */
 
 struct ipv4_service_contents {
     const char *       addr;
@@ -5293,6 +6643,10 @@ struct ipv4_service_contents en1_20_never = {
     "10.0.0.20", "255.255.255.0", NULL,                "10.0.0.1",     "en1",  20,  &kSCValNetServicePrimaryRankNever
 };
 
+struct ipv4_service_contents en0_linklocal = {
+    "169.254.22.44", "255.255.0.0", NULL,      NULL,           "en0",  0xfffff,  NULL
+};
+
 struct ipv4_service_contents * test1[] = {
     &en0_40,
     &en0_15,
@@ -5407,6 +6761,11 @@ struct ipv4_service_contents * test14[] = {
     NULL
 };
 
+struct ipv4_service_contents * test15[] = {
+    &en0_linklocal,
+    NULL
+};
+
 static void
 dict_add_string(CFMutableDictionaryRef dict, CFStringRef prop_name,
                const char * str)
@@ -5548,7 +6907,7 @@ run_test(const char * name, struct ipv4_service_contents * * this_test)
        }
        if ((S_IPMonitor_debug & kDebugFlag4) != 0) {
            descr = IPv4RouteListCopyDescription(r);
-           SCLog(TRUE, LOG_NOTICE, CFSTR("test: Adding %@"), descr);
+           SCPrint(TRUE, stdout, CFSTR("test: Adding %@\n"), descr);
            CFRelease(descr);
        }
 
@@ -5568,7 +6927,7 @@ run_test(const char * name, struct ipv4_service_contents * * this_test)
     if ((S_IPMonitor_debug & kDebugFlag4) != 0) {
        if (routes1 != NULL) {
            descr = IPv4RouteListCopyDescription(routes1);
-           SCLog(TRUE, LOG_NOTICE, CFSTR("Routes are %@"), descr);
+           SCPrint(TRUE, stdout, CFSTR("Routes are %@\n"), descr);
            CFRelease(descr);
        }
     }
@@ -5591,7 +6950,7 @@ run_test(const char * name, struct ipv4_service_contents * * this_test)
        }
        if ((S_IPMonitor_debug & kDebugFlag4) != 0) {
            descr = IPv4RouteListCopyDescription(r);
-           SCLog(TRUE, LOG_NOTICE, CFSTR("test: Adding %@"), descr);
+           SCPrint(TRUE, stdout, CFSTR("test: Adding %@\n"), descr);
            CFRelease(descr);
        }
        if ((*scan_test)->primaryRank != NULL) {
@@ -5608,7 +6967,7 @@ run_test(const char * name, struct ipv4_service_contents * * this_test)
     if ((S_IPMonitor_debug & kDebugFlag4) != 0) {
        if (routes2 != NULL) {
            descr = IPv4RouteListCopyDescription(routes2);
-           SCLog(TRUE, LOG_NOTICE, CFSTR("Routes are %@"), descr);
+           SCPrint(TRUE, stdout, CFSTR("Routes are %@\n"), descr);
            CFRelease(descr);
        }
     }
@@ -5736,6 +7095,11 @@ main(int argc, char **argv)
        fprintf(stderr, "test5 failed\n");
        exit(1);
     }
+    if (run_test("test15", test15) == FALSE) {
+       fprintf(stderr, "test15 failed\n");
+       exit(1);
+    }
+
 
     printf("\nCompare 1 to 2:\n");
     compare_tests(test1, test2);
diff --git a/Plugins/IPMonitor/ip_plugin.h b/Plugins/IPMonitor/ip_plugin.h
new file mode 100644 (file)
index 0000000..ab52f1f
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2012, 2013 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@
+ */
+
+/*
+ * ip_plugin.h
+ * - header for IPMonitor.bundle
+ */
+
+#ifndef        _IP_PLUGIN_H
+#define        _IP_PLUGIN_H
+
+#include <SystemConfiguration/SCPrivate.h>
+
+#define kIsNULL                                CFSTR("IsNULL") /* CFBoolean */
+
+#if    ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 60000))
+
+#define my_log(__level, fmt, ...)      SCLoggerLog(my_log_get_logger(), __level, CFSTR(fmt), ## __VA_ARGS__)
+SCLoggerRef my_log_get_logger();
+
+/*
+ * IPv4 Service Dict keys: IPv4DictRoutes, IPv4DictService
+ *
+ * The IPv4 service dictionary contains two sub-dictionaries:
+ *     Routes          IPv4RouteList
+ *      Service                dictionary containing kSCEntNetIPv4 keys
+ */
+#define kIPv4DictRoutes                CFSTR("Routes")
+#define        kIPv4DictService                CFSTR("Service")
+
+boolean_t
+cfstring_to_ip(CFStringRef str, struct in_addr * ip_p);
+
+boolean_t
+cfstring_to_ip6(CFStringRef str, struct in6_addr * ip6_p);
+
+#else  // ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 60000))
+
+#define my_log(__level, fmt, ...)      SCLog(TRUE, __level, CFSTR(fmt), ## __VA_ARGS__)
+
+#endif // ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 60000))
+
+#endif // _IP_PLUGIN_H
index 76d60fac9f07fc09d1321439df1cfb98c64a5953..f8ac69c31aef2b73c8fee4a58c06572799d062d1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2011, 2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -323,8 +323,8 @@ copy_supplemental_proxies(CFArrayRef proxies, Boolean skip)
 }
 
 
-static CFDictionaryRef
-copy_scoped_proxies(CFDictionaryRef services, CFArrayRef service_order)
+static CFArrayRef
+service_order_copy_all(CFDictionaryRef services, CFArrayRef service_order)
 {
        const void *            keys_q[N_QUICK];
        const void **           keys    = keys_q;
@@ -332,11 +332,12 @@ copy_scoped_proxies(CFDictionaryRef services, CFArrayRef service_order)
        CFIndex                 n_order;
        CFIndex                 n_services;
        CFMutableArrayRef       order;
-       CFMutableDictionaryRef  scoped  = NULL;
 
+       // ensure that we process all services in order
        n_services = isA_CFDictionary(services) ? CFDictionaryGetCount(services) : 0;
        if (n_services == 0) {
-               return NULL;            // if no services
+               // if no services
+               return NULL;
        }
 
        // ensure that we process all services in order
@@ -344,7 +345,7 @@ copy_scoped_proxies(CFDictionaryRef services, CFArrayRef service_order)
        n_order = isA_CFArray(service_order) ? CFArrayGetCount(service_order) : 0;
        if (n_order > 0) {
                order = CFArrayCreateMutableCopy(NULL, 0, service_order);
-       } else{
+       } else {
                order = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
        }
 
@@ -353,7 +354,7 @@ copy_scoped_proxies(CFDictionaryRef services, CFArrayRef service_order)
        }
        CFDictionaryGetKeysAndValues(services, keys, NULL);
        for (i = 0; i < n_services; i++) {
-               CFStringRef     serviceID = (CFStringRef)keys[i];
+               CFStringRef     serviceID       = (CFStringRef)keys[i];
 
                if (!CFArrayContainsValue(order, CFRangeMake(0, n_order), serviceID)) {
                        CFArrayAppendValue(order, serviceID);
@@ -364,13 +365,96 @@ copy_scoped_proxies(CFDictionaryRef services, CFArrayRef service_order)
                CFAllocatorDeallocate(NULL, keys);
        }
 
+       return order;
+}
+
+
+static CFDictionaryRef
+copy_app_layer_vpn_proxies(CFDictionaryRef services, CFArrayRef order, CFDictionaryRef services_info)
+{
+       CFMutableDictionaryRef  app_layer_proxies       = NULL;
+       CFIndex                 i;
+       CFIndex                 n_order;
+
+       if (!isA_CFDictionary(services_info)) {
+               return NULL;
+       }
+
        // iterate over services
 
+       n_order = isA_CFArray(order) ? CFArrayGetCount(order) : 0;
        for (i = 0; i < n_order; i++) {
+               CFMutableDictionaryRef  newProxy;
                CFDictionaryRef         proxy;
+               CFDictionaryRef         service;
+               CFStringRef             serviceID;
+               CFDictionaryRef         vpn;
+               CFStringRef             vpn_key;
+
+               serviceID = CFArrayGetValueAtIndex(order, i);
+               service = CFDictionaryGetValue(services, serviceID);
+               if (!isA_CFDictionary(service)) {
+                       // if no service
+                       continue;
+               }
+
+               proxy = CFDictionaryGetValue(service, kSCEntNetProxies);
+               if (!isA_CFDictionary(proxy)) {
+                       // if no proxy
+                       continue;
+               }
+
+               vpn_key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+                                                                     kSCDynamicStoreDomainSetup,
+                                                                     serviceID,
+                                                                     kSCEntNetVPN);
+               vpn = CFDictionaryGetValue(services_info, vpn_key);
+               CFRelease(vpn_key);
+
+               if (!isA_CFDictionary(vpn) || !CFDictionaryContainsKey(vpn, kSCPropNetVPNAppRules)) {
+                       // if not app-layer vpn
+                       continue;
+               }
+
+               if ((app_layer_proxies != NULL) &&
+                   CFDictionaryContainsKey(app_layer_proxies, serviceID)) {
+                       // if we've already processed this [app_layer_proxies] interface
+                       continue;
+               }
+
+               // add [app_layer_proxies] proxy entry
+               newProxy = CFDictionaryCreateMutableCopy(NULL, 0, proxy);
+               CFDictionaryRemoveValue(newProxy, kSCPropNetProxiesSupplementalMatchDomains);
+               CFDictionaryRemoveValue(newProxy, kSCPropNetProxiesSupplementalMatchOrders);
+               if (app_layer_proxies == NULL) {
+                       app_layer_proxies = CFDictionaryCreateMutable(NULL,
+                                                                     0,
+                                                                     &kCFTypeDictionaryKeyCallBacks,
+                                                                     &kCFTypeDictionaryValueCallBacks);
+               }
+               CFDictionarySetValue(app_layer_proxies, serviceID, newProxy);
+               CFRelease(newProxy);
+       }
+
+       return app_layer_proxies;
+}
+
+
+static CFDictionaryRef
+copy_scoped_proxies(CFDictionaryRef services, CFArrayRef order)
+{
+       CFIndex                 i;
+       CFIndex                 n_order;
+       CFMutableDictionaryRef  scoped  = NULL;
+
+       // iterate over services
+
+       n_order = isA_CFArray(order) ? CFArrayGetCount(order) : 0;
+       for (i = 0; i < n_order; i++) {
                char                    if_name[IF_NAMESIZE];
                CFStringRef             interface;
                CFMutableDictionaryRef  newProxy;
+               CFDictionaryRef         proxy;
                CFDictionaryRef         service;
                CFStringRef             serviceID;
 
@@ -425,7 +509,6 @@ copy_scoped_proxies(CFDictionaryRef services, CFArrayRef service_order)
                CFRelease(interface);
        }
 
-       CFRelease(order);
        return scoped;
 }
 
@@ -548,7 +631,8 @@ __private_extern__
 CF_RETURNS_RETAINED CFDictionaryRef
 proxy_configuration_update(CFDictionaryRef     defaultProxy,
                           CFDictionaryRef      services,
-                          CFArrayRef           serviceOrder)
+                          CFArrayRef           serviceOrder,
+                          CFDictionaryRef      servicesInfo)
 {
        CFIndex                 i;
        CFMutableDictionaryRef  myDefault;
@@ -618,8 +702,10 @@ proxy_configuration_update(CFDictionaryRef defaultProxy,
        // establish proxy configuration
 
        if (n_proxies > 0) {
+               CFDictionaryRef         app_layer;
                CFDictionaryRef         scoped;
-               Boolean                 skip    = FALSE;
+               CFArrayRef              serviceOrderAll;
+               Boolean                 skip            = FALSE;
                CFArrayRef              supplemental;
 
                proxy = CFArrayGetValueAtIndex(proxies, 0);
@@ -636,6 +722,8 @@ proxy_configuration_update(CFDictionaryRef  defaultProxy,
                                                             &kCFTypeDictionaryValueCallBacks);
                }
 
+               serviceOrderAll = service_order_copy_all(services, serviceOrder);
+
                // collect (and add) any "supplemental" proxy configurations
 
                supplemental = copy_supplemental_proxies(proxies, skip);
@@ -646,11 +734,23 @@ proxy_configuration_update(CFDictionaryRef        defaultProxy,
 
                // collect (and add) any "scoped" proxy configurations
 
-               scoped = copy_scoped_proxies(services, serviceOrder);
+               scoped = copy_scoped_proxies(services, serviceOrderAll);
                if (scoped != NULL) {
                        CFDictionarySetValue(newProxy, kSCPropNetProxiesScoped, scoped);
                        CFRelease(scoped);
                }
+
+               // collect (and add) any "services" based proxy configurations
+
+               app_layer = copy_app_layer_vpn_proxies(services, serviceOrderAll, servicesInfo);
+               if (app_layer != NULL) {
+                       CFDictionarySetValue(newProxy, kSCPropNetProxiesServices, app_layer);
+                       CFRelease(app_layer);
+               }
+
+               if (serviceOrderAll != NULL) {
+                       CFRelease(serviceOrderAll);
+               }
        } else {
                newProxy = NULL;
        }
@@ -866,7 +966,8 @@ main(int argc, char **argv)
        proxy_configuration_init(CFBundleGetMainBundle());
        newProxy = proxy_configuration_update(primary_proxy,
                                              service_state_dict,
-                                             service_order);
+                                             service_order,
+                                             NULL);
        if (newProxy != NULL) {
                SCPrint(TRUE, stdout, CFSTR("%@\n"), newProxy);
                CFRelease(newProxy);
index fbb233c0c8d27065e1e467baae518d31e01cace4..e86bd535df4be7de1681d9526658ffee4f3e9bf7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2011-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -34,16 +34,15 @@ CFBooleanRef        G_supplemental_proxies_follow_dns;
 
 __BEGIN_DECLS
 
-__private_extern__
 void
 proxy_configuration_init       (CFBundleRef            bundle);
 
 
-__private_extern__
 CF_RETURNS_RETAINED CFDictionaryRef
 proxy_configuration_update     (CFDictionaryRef        defaultProxy,
                                 CFDictionaryRef        services,
-                                CFArrayRef             serviceOrder);
+                                CFArrayRef             serviceOrder,
+                                CFDictionaryRef        servicesInfo);
 
 __END_DECLS
 
index 6ebcafd1c6ec1ece56f79fdaa2fc232197e0010f..b9ff91321d0808a5e83da185d46ef49ca401ab66 100644 (file)
@@ -40,6 +40,7 @@
 #include <SystemConfiguration/SCPrivate.h>
 
 #include <notify.h>
+#include "ip_plugin.h"
 
 static SCDynamicStoreRef       store           = NULL;
 static CFRunLoopSourceRef      rls             = NULL;
@@ -63,7 +64,7 @@ set_hostname(CFStringRef hostname)
                char    new_name[MAXHOSTNAMELEN];
 
                if (gethostname(old_name, sizeof(old_name)) == -1) {
-                       SCLog(TRUE, LOG_ERR, CFSTR("gethostname() failed: %s"), strerror(errno));
+                       my_log(LOG_ERR, "gethostname() failed: %s", strerror(errno));
                        old_name[0] = '\0';
                }
 
@@ -71,7 +72,7 @@ set_hostname(CFStringRef hostname)
                                            new_name,
                                            sizeof(new_name),
                                            kCFStringEncodingUTF8) == NULL) {
-                       SCLog(TRUE, LOG_ERR, CFSTR("could not convert [new] hostname"));
+                       my_log(LOG_ERR, "could not convert [new] hostname");
                        new_name[0] = '\0';
                }
 
@@ -81,22 +82,22 @@ set_hostname(CFStringRef hostname)
                        if (sethostname(new_name, strlen(new_name)) == 0) {
                                uint32_t        status;
 
-                               SCLog(TRUE, LOG_NOTICE,
-                                     CFSTR("setting hostname to \"%s\""),
-                                     new_name);
+                               my_log(LOG_NOTICE,
+                                      "setting hostname to \"%s\"",
+                                      new_name);
 
                                status = notify_post(HOSTNAME_NOTIFY_KEY);
                                if (status != NOTIFY_STATUS_OK) {
-                                       SCLog(TRUE, LOG_ERR,
-                                             CFSTR("notify_post(" HOSTNAME_NOTIFY_KEY ") failed: error=%lu"),
-                                             status);
+                                       my_log(LOG_ERR,
+                                              "notify_post(" HOSTNAME_NOTIFY_KEY ") failed: error=%lu",
+                                              status);
                                }
                        } else {
-                               SCLog(TRUE, LOG_ERR,
-                                     CFSTR("sethostname(%s, %d) failed: %s"),
-                                     new_name,
-                                     strlen(new_name),
-                                     strerror(errno));
+                               my_log(LOG_ERR,
+                                      "sethostname(%s, %d) failed: %s",
+                                      new_name,
+                                      strlen(new_name),
+                                      strerror(errno));
                        }
                }
        }
@@ -319,11 +320,12 @@ reverseDNSComplete(int32_t status, char *host, char *serv, void *context)
 
        (void) gettimeofday(&dnsQueryComplete, NULL);
        timersub(&dnsQueryComplete, &dnsQueryStart, &dnsQueryElapsed);
-       SCLog(_verbose, LOG_INFO,
-             CFSTR("async DNS complete%s (query time = %d.%3.3d)"),
-             ((status == 0) && (host != NULL)) ? "" : ", host not found",
-             dnsQueryElapsed.tv_sec,
-             dnsQueryElapsed.tv_usec / 1000);
+       if (_verbose) {
+               my_log(LOG_INFO, "async DNS complete%s (query time = %d.%3.3d)",
+                      ((status == 0) && (host != NULL)) ? "" : ", host not found",
+                      dnsQueryElapsed.tv_sec,
+                      dnsQueryElapsed.tv_usec / 1000);
+       }
 
        // use reverse DNS name, if available
 
@@ -335,7 +337,7 @@ reverseDNSComplete(int32_t status, char *host, char *serv, void *context)
                        if (host != NULL) {
                                hostname = CFStringCreateWithCString(NULL, host, kCFStringEncodingUTF8);
                                if (hostname != NULL) {
-                                       SCLog(TRUE, LOG_INFO, CFSTR("hostname (reverse DNS query) = %@"), hostname);
+                                       my_log(LOG_INFO, "hostname (reverse DNS query) = %@", hostname);
                                        set_hostname(hostname);
                                        CFRelease(hostname);
                                        goto done;
@@ -356,7 +358,7 @@ reverseDNSComplete(int32_t status, char *host, char *serv, void *context)
                        /*
                         * Hmmmm...
                         */
-                       SCLog(TRUE, LOG_ERR, CFSTR("getnameinfo() failed: %s"), gai_strerror(status));
+                       my_log(LOG_ERR, "getnameinfo() failed: %s", gai_strerror(status));
        }
 
        // get local (multicast DNS) name, if available
@@ -365,8 +367,9 @@ reverseDNSComplete(int32_t status, char *host, char *serv, void *context)
        if (hostname != NULL) {
                CFMutableStringRef      localName;
 
-               SCLog(TRUE, LOG_INFO, CFSTR("hostname (multicast DNS) = %@"), hostname);
+               my_log(LOG_INFO, "hostname (multicast DNS) = %@", hostname);
                localName = CFStringCreateMutableCopy(NULL, 0, hostname);
+               assert(localName != NULL);
                CFStringAppend(localName, CFSTR(".local"));
                set_hostname(localName);
                CFRelease(localName);
@@ -409,7 +412,7 @@ getnameinfo_async_handleCFReply(CFMachPortRef port, void *msg, CFIndex size, voi
                // we've received a callback on the async DNS port but since the
                // associated CFMachPort doesn't match than the request must have
                // already been cancelled.
-               SCLog(TRUE, LOG_ERR, CFSTR("getnameinfo_async_handleCFReply(): port != dnsPort"));
+               my_log(LOG_ERR, "getnameinfo_async_handleCFReply(): port != dnsPort");
                return;
        }
 
@@ -459,13 +462,13 @@ start_dns_query(SCDynamicStoreRef store, CFStringRef address)
        Boolean                         ok;
 
        if (_SC_cfstring_to_cstring(address, buf, sizeof(buf), kCFStringEncodingASCII) == NULL) {
-               SCLog(TRUE, LOG_ERR, CFSTR("could not convert [primary] address"));
+               my_log(LOG_ERR, "could not convert [primary] address");
                return;
        }
 
        if (_SC_string_to_sockaddr(buf, AF_UNSPEC, (void *)&addr, sizeof(addr)) == NULL) {
                /* if not an IP[v6] address */
-               SCLog(TRUE, LOG_ERR, CFSTR("could not parse [primary] address"));
+               my_log(LOG_ERR, "could not parse [primary] address");
                return;
        }
 
@@ -543,7 +546,7 @@ update_hostname(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info)
 
        hostname = copy_static_name();
        if (hostname != NULL) {
-               SCLog(TRUE, LOG_INFO, CFSTR("hostname (static) = %@"), hostname);
+               my_log(LOG_INFO, "hostname (static) = %@", hostname);
                set_hostname(hostname);
                goto done;
        }
@@ -552,7 +555,7 @@ update_hostname(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info)
 
        hostname = copy_prefs_hostname(store);
        if (hostname != NULL) {
-               SCLog(TRUE, LOG_INFO, CFSTR("hostname (prefs) = %@"), hostname);
+               my_log(LOG_INFO, "hostname (prefs) = %@", hostname);
                set_hostname(hostname);
                goto done;
        }
@@ -568,7 +571,7 @@ update_hostname(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info)
 
        hostname = copy_dhcp_hostname(serviceID);
        if (hostname != NULL) {
-               SCLog(TRUE, LOG_INFO, CFSTR("hostname (DHCP) = %@"), hostname);
+               my_log(LOG_INFO, "hostname (DHCP) = %@", hostname);
                set_hostname(hostname);
                goto done;
        }
@@ -590,8 +593,9 @@ update_hostname(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info)
        if (hostname != NULL) {
                CFMutableStringRef      localName;
 
-               SCLog(TRUE, LOG_INFO, CFSTR("hostname (multicast DNS) = %@"), hostname);
+               my_log(LOG_INFO, "hostname (multicast DNS) = %@", hostname);
                localName = CFStringCreateMutableCopy(NULL, 0, hostname);
+               assert(localName != NULL);
                CFStringAppend(localName, CFSTR(".local"));
                set_hostname(localName);
                CFRelease(localName);
@@ -628,9 +632,9 @@ load_hostname(Boolean verbose)
 
        store = SCDynamicStoreCreate(NULL, CFSTR("set-hostname"), update_hostname, NULL);
        if (store == NULL) {
-               SCLog(TRUE, LOG_ERR,
-                     CFSTR("SCDynamicStoreCreate() failed: %s"),
-                     SCErrorString(SCError()));
+               my_log(LOG_ERR,
+                      "SCDynamicStoreCreate() failed: %s",
+                      SCErrorString(SCError()));
                goto error;
        }
 
@@ -673,17 +677,17 @@ load_hostname(Boolean verbose)
 
        /* register the keys/patterns */
        if (!SCDynamicStoreSetNotificationKeys(store, keys, patterns)) {
-               SCLog(TRUE, LOG_ERR,
-                     CFSTR("SCDynamicStoreSetNotificationKeys() failed: %s"),
-                     SCErrorString(SCError()));
+               my_log(LOG_ERR,
+                      "SCDynamicStoreSetNotificationKeys() failed: %s",
+                      SCErrorString(SCError()));
                goto error;
        }
 
        rls = SCDynamicStoreCreateRunLoopSource(NULL, store, 0);
        if (!rls) {
-               SCLog(TRUE, LOG_ERR,
-                     CFSTR("SCDynamicStoreCreateRunLoopSource() failed: %s"),
-                     SCErrorString(SCError()));
+               my_log(LOG_ERR,
+                      "SCDynamicStoreCreateRunLoopSource() failed: %s",
+                      SCErrorString(SCError()));
                goto error;
        }
        CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
index 3315cce2ef281477bda21455cf773a568c384f82..c8a686e92bae34fae412ff4dfd91d1ee28549cde 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2006, 2011, 2012 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -29,7 +29,6 @@
 
 __BEGIN_DECLS
 
-__private_extern__
 void   load_hostname           (Boolean        verbose);
 
 __END_DECLS
index 8c06cd69d528668989842983319dc047350155f8..01027ee679e849dc4856fbb73a0a4b76b5572cab 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2006-2012 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -51,6 +51,8 @@
 #include <SystemConfiguration/SCValidation.h>
 #include <SystemConfiguration/SCPrivate.h>             // for SCLog(), SCPrint()
 
+#include "ip_plugin.h"
+
 #define        HW_MODEL_LEN            64                      // Note: must be >= NETBIOS_NAME_LEN (below)
 
 #define        NETBIOS_NAME_LEN        16
@@ -98,7 +100,7 @@ boottime(void)
                size_t          tv_len  = sizeof(tv);
 
                if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), &tv, &tv_len, NULL, 0) == -1) {
-                       SCLog(TRUE, LOG_ERR, CFSTR("sysctl() CTL_KERN/KERN_BOOTTIME failed: %s"), strerror(errno));
+                       my_log(LOG_ERR, "sysctl() CTL_KERN/KERN_BOOTTIME failed: %s", strerror(errno));
                        return kCFAbsoluteTimeIntervalSince1970;
                }
 
@@ -125,7 +127,7 @@ copy_default_name(void)
        bzero(&hwModel, sizeof(hwModel));
        ret = sysctl(mib, sizeof(mib) / sizeof(mib[0]), &hwModel, &n, NULL, 0);
        if (ret != 0) {
-               SCLog(TRUE, LOG_ERR, CFSTR("sysctl() CTL_HW/HW_MODEL failed: %s"), strerror(errno));
+               my_log(LOG_ERR, "sysctl() CTL_HW/HW_MODEL failed: %s", strerror(errno));
                return NULL;
        }
 
@@ -278,17 +280,17 @@ smb_set_configuration(SCDynamicStoreRef store, CFDictionaryRef dict)
 
        prefs = SCPreferencesCreate(NULL, CFSTR("smb-configuration"), CFSTR(kSMBPreferencesAppID));
        if (prefs == NULL) {
-               SCLog(TRUE, LOG_ERR,
-                     CFSTR("smb_set_configuration: SCPreferencesCreate() failed: %s"),
-                     SCErrorString(SCError()));
+               my_log(LOG_ERR,
+                      "smb_set_configuration: SCPreferencesCreate() failed: %s",
+                      SCErrorString(SCError()));
                return;
        }
 
        ok = SCPreferencesLock(prefs, TRUE);
        if (!ok) {
-               SCLog(TRUE, LOG_ERR,
-                     CFSTR("smb_set_configuration: SCPreferencesLock() failed: %s"),
-                     SCErrorString(SCError()));
+               my_log(LOG_ERR,
+                      "smb_set_configuration: SCPreferencesLock() failed: %s",
+                      SCErrorString(SCError()));
                goto done;
        }
 
@@ -329,7 +331,8 @@ smb_set_configuration(SCDynamicStoreRef store, CFDictionaryRef dict)
                        __CFStringGetInstallationEncodingAndRegion((uint32_t *)&macEncoding, &macRegion);
                }
                _SC_dos_encoding_and_codepage(macEncoding, macRegion, &dosEncoding, &dosCodepage);
-               str = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), dosCodepage);
+               str = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), (unsigned int)dosCodepage);
+               assert(str != NULL);
                update_pref(prefs, CFSTR(kSMBPrefDOSCodePage), str, &changed);
                CFRelease(str);
        }
@@ -381,17 +384,19 @@ smb_set_configuration(SCDynamicStoreRef store, CFDictionaryRef dict)
        if (changed) {
                ok = SCPreferencesCommitChanges(prefs);
                if (!ok) {
-                       SCLog((SCError() != EROFS), LOG_ERR,
-                             CFSTR("smb_set_configuration: SCPreferencesCommitChanges() failed: %s"),
-                             SCErrorString(SCError()));
+                       if ((SCError() != EROFS)) {
+                               my_log(LOG_ERR,
+                                      "smb_set_configuration: SCPreferencesCommitChanges() failed: %s",
+                                      SCErrorString(SCError()));
+                       }
                        goto done;
                }
 
                ok = SCPreferencesApplyChanges(prefs);
                if (!ok) {
-                       SCLog(TRUE, LOG_ERR,
-                             CFSTR("smb_set_configuration: SCPreferencesApplyChanges() failed: %s"),
-                             SCErrorString(SCError()));
+                       my_log(LOG_ERR,
+                              "smb_set_configuration: SCPreferencesApplyChanges() failed: %s",
+                              SCErrorString(SCError()));
                        goto done;
                }
        }
@@ -479,11 +484,13 @@ reverseDNSComplete(int32_t status, char *host, char *serv, void *context)
 
        (void) gettimeofday(&dnsQueryComplete, NULL);
        timersub(&dnsQueryComplete, &dnsQueryStart, &dnsQueryElapsed);
-       SCLog(_verbose, LOG_INFO,
-             CFSTR("async DNS complete%s (query time = %d.%3.3d)"),
-             ((status == 0) && (host != NULL)) ? "" : ", host not found",
-             dnsQueryElapsed.tv_sec,
-             dnsQueryElapsed.tv_usec / 1000);
+       if (_verbose) {
+               my_log(LOG_INFO,
+                      "async DNS complete%s (query time = %d.%3.3d)",
+                      ((status == 0) && (host != NULL)) ? "" : ", host not found",
+                      dnsQueryElapsed.tv_sec,
+                      dnsQueryElapsed.tv_usec / 1000);
+       }
 
        // get network configuration
        dict = smb_copy_global_configuration(store);
@@ -491,7 +498,7 @@ reverseDNSComplete(int32_t status, char *host, char *serv, void *context)
        // use NetBIOS name from network configuration (if available)
        name = CFDictionaryGetValue(dict, kSCPropNetSMBNetBIOSName);
        if ((name != NULL) && _SC_CFStringIsValidNetBIOSName(name)) {
-               SCLog(TRUE, LOG_INFO, CFSTR("NetBIOS name (network configuration) = %@"), name);
+               my_log(LOG_INFO, "NetBIOS name (network configuration) = %@", name);
                goto set;
        }
 
@@ -514,7 +521,7 @@ reverseDNSComplete(int32_t status, char *host, char *serv, void *context)
                                        if (_SC_CFStringIsValidNetBIOSName(name)) {
                                                CFMutableDictionaryRef  newDict;
 
-                                               SCLog(TRUE, LOG_INFO, CFSTR("NetBIOS name (reverse DNS query) = %@"), name);
+                                               my_log(LOG_INFO, "NetBIOS name (reverse DNS query) = %@", name);
                                                newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
                                                CFDictionarySetValue(newDict, kSCPropNetSMBNetBIOSName, name);
                                                CFRelease(dict);
@@ -541,7 +548,7 @@ reverseDNSComplete(int32_t status, char *host, char *serv, void *context)
                        /*
                         * Hmmmm...
                         */
-                       SCLog(TRUE, LOG_ERR, CFSTR("getnameinfo() failed: %s"), gai_strerror(status));
+                       my_log(LOG_ERR,"getnameinfo() failed: %s", gai_strerror(status));
        }
 
        // try local (multicast DNS) name, if available
@@ -550,7 +557,7 @@ reverseDNSComplete(int32_t status, char *host, char *serv, void *context)
                if (_SC_CFStringIsValidNetBIOSName(name)) {
                        CFMutableDictionaryRef  newDict;
 
-                       SCLog(TRUE, LOG_INFO, CFSTR("NetBIOS name (multicast DNS) = %@"), name);
+                       my_log(LOG_INFO, "NetBIOS name (multicast DNS) = %@", name);
                        newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
                        CFDictionarySetValue(newDict, kSCPropNetSMBNetBIOSName, name);
                        CFRelease(dict);
@@ -566,7 +573,7 @@ reverseDNSComplete(int32_t status, char *host, char *serv, void *context)
        if (name != NULL) {
                CFMutableDictionaryRef  newDict;
 
-               SCLog(TRUE, LOG_INFO, CFSTR("NetBIOS name (default) = %@"), name);
+               my_log(LOG_INFO, "NetBIOS name (default) = %@", name);
                newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
                CFDictionarySetValue(newDict, kSCPropNetSMBNetBIOSName, name);
                CFRelease(dict);
@@ -609,7 +616,7 @@ getnameinfo_async_handleCFReply(CFMachPortRef port, void *msg, CFIndex size, voi
                // we've received a callback on the async DNS port but since the
                // associated CFMachPort doesn't match than the request must have
                // already been cancelled.
-               SCLog(TRUE, LOG_ERR, CFSTR("getnameinfo_async_handleCFReply(): port != dnsPort"));
+               my_log(LOG_ERR, "getnameinfo_async_handleCFReply(): port != dnsPort");
                return;
        }
 
@@ -656,13 +663,13 @@ start_dns_query(SCDynamicStoreRef store, CFStringRef address)
        Boolean                         ok      = FALSE;
 
        if (_SC_cfstring_to_cstring(address, buf, sizeof(buf), kCFStringEncodingASCII) == NULL) {
-               SCLog(TRUE, LOG_ERR, CFSTR("could not convert [primary] address"));
+               my_log(LOG_ERR, "could not convert [primary] address");
                return FALSE;
        }
 
        if (_SC_string_to_sockaddr(buf, AF_UNSPEC, (void *)&addr, sizeof(addr)) == NULL) {
                /* if not an IP[v6] address */
-               SCLog(TRUE, LOG_ERR, CFSTR("could not parse [primary] address"));
+               my_log(LOG_ERR, "could not parse [primary] address");
                return FALSE;
        }
 
@@ -730,7 +737,7 @@ smb_update_configuration(__unused CFRunLoopTimerRef _timer, void *info)
        // use NetBIOS name from network configuration (if available)
        name = CFDictionaryGetValue(dict, kSCPropNetSMBNetBIOSName);
        if ((name != NULL) && _SC_CFStringIsValidNetBIOSName(name)) {
-               SCLog(TRUE, LOG_INFO, CFSTR("NetBIOS name (network configuration) = %@"), name);
+               my_log(LOG_INFO, "NetBIOS name (network configuration) = %@", name);
                goto set;
        }
 
@@ -763,7 +770,7 @@ smb_update_configuration(__unused CFRunLoopTimerRef _timer, void *info)
                if (_SC_CFStringIsValidNetBIOSName(name)) {
                        CFMutableDictionaryRef  newDict;
 
-                       SCLog(TRUE, LOG_INFO, CFSTR("NetBIOS name (multicast DNS) = %@"), name);
+                       my_log(LOG_INFO, "NetBIOS name (multicast DNS) = %@", name);
                        newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
                        CFDictionarySetValue(newDict, kSCPropNetSMBNetBIOSName, name);
                        CFRelease(dict);
@@ -779,7 +786,7 @@ smb_update_configuration(__unused CFRunLoopTimerRef _timer, void *info)
        if (name != NULL) {
                CFMutableDictionaryRef  newDict;
 
-               SCLog(TRUE, LOG_INFO, CFSTR("NetBIOS name (default) = %@"), name);
+               my_log(LOG_INFO, "NetBIOS name (default) = %@", name);
                newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
                CFDictionarySetValue(newDict, kSCPropNetSMBNetBIOSName, name);
                CFRelease(dict);
@@ -867,9 +874,9 @@ load_smb_configuration(Boolean verbose)
 
        store = SCDynamicStoreCreate(NULL, CFSTR("smb-configuration"), configuration_changed, NULL);
        if (store == NULL) {
-               SCLog(TRUE, LOG_ERR,
-                     CFSTR("SCDynamicStoreCreate() failed: %s"),
-                     SCErrorString(SCError()));
+               my_log(LOG_ERR,
+                      "SCDynamicStoreCreate() failed: %s",
+                      SCErrorString(SCError()));
                goto error;
        }
 
@@ -911,17 +918,17 @@ load_smb_configuration(Boolean verbose)
 
        /* register the keys/patterns */
        if (!SCDynamicStoreSetNotificationKeys(store, keys, patterns)) {
-               SCLog(TRUE, LOG_ERR,
-                     CFSTR("SCDynamicStoreSetNotificationKeys() failed: %s"),
-                     SCErrorString(SCError()));
+               my_log(LOG_ERR,
+                      "SCDynamicStoreSetNotificationKeys() failed: %s",
+                      SCErrorString(SCError()));
                goto error;
        }
 
        rls = SCDynamicStoreCreateRunLoopSource(NULL, store, 0);
        if (!rls) {
-               SCLog(TRUE, LOG_ERR,
-                     CFSTR("SCDynamicStoreCreateRunLoopSource() failed: %s"),
-                     SCErrorString(SCError()));
+               my_log(LOG_ERR,
+                      "SCDynamicStoreCreateRunLoopSource() failed: %s",
+                      SCErrorString(SCError()));
                goto error;
        }
        CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
index d1fdf3ae95af5c96aa020768a6ba11029e09914e..babfb1bd6e6540d4f6a5428b820006e46080c55e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2006, 2011, 2012 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -28,7 +28,6 @@
 
 __BEGIN_DECLS
 
-__private_extern__
 void   load_smb_configuration          (Boolean        verbose);
 
 __END_DECLS
index 924de28662b8476e173d8fb572b69026e44e0e32..90cb275ccef652b6a348e7f7288e8298a6392628 100644 (file)
@@ -1,2 +1,9 @@
 #!/bin/sh
-sed '/Process [0-9][0-9]*: [0-9][0-9]* nodes malloced/d; s/^\(Process \)[0-9][0-9]*:\(.*\)/\1XXXX\2/'
+sed -e 's/^\(Process:.*\[\)[0-9][0-9]*/\1XXXX/'                        \
+    -e 's/^\(Load Address:.*0x\)[0-9a-f][0-9a-f]*/\1XXXX/'     \
+    -e 's/^\(Parent Process:.*\[\)[0-9][0-9]*/\1XXXX/'         \
+    -e 's/^\(Date\/Time: *\)[0-9].*/\1XXXX/'                   \
+    -e '/Process [0-9][0-9]*: [0-9][0-9]* nodes malloced/d'    \
+    -e 's/^\(Process \)[0-9][0-9]*:\(.*\)/\1XXXX\2/'           \
+    -e 's/^\(Path: \)\(.*$\)/\1XXXX/'                          \
+    -e 's/^\(OS Version: \)\(.*$\)/\1XXXX/'
index 410103d5248adb5b08261dac42cf070e8ba4d98a..aaadc627b33863d84c87723699ba9676f288e324 100644 (file)
@@ -4,37 +4,30 @@ test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.12
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.12 Ifp en0 Ifa 10.0.0.12
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.19
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.19 Ifp en0 Ifa 10.0.0.19
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 192.168.2.1 Ifp fw0 Ifa 192.168.2.30
  1. Dest 192.168.2.0 Mask 255.255.255.0 Gate 192.168.2.30 Ifp fw0 Ifa 192.168.2.30
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.11
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.11 Ifp en0 Ifa 10.0.0.11
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en1 Ifa 10.0.0.20
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.20 Ifp en1 Ifa 10.0.0.20
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.13
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.13 Ifp en0 Ifa 10.0.0.13
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.10
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.10 Ifp en0 Ifa 10.0.0.10
 }
-
 Routes are <IPv4RouteList[6]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.10
  1. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en1 Ifa 10.0.0.20 [SCOPED]
@@ -43,42 +36,34 @@ Routes are <IPv4RouteList[6]> = {
  4. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.20 Ifp en1 Ifa 10.0.0.20 [SCOPED]
  5. Dest 192.168.2.0 Mask 255.255.255.0 Gate 192.168.2.30 Ifp fw0 Ifa 192.168.2.30
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.10
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.10 Ifp en0 Ifa 10.0.0.10
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.13
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.13 Ifp en0 Ifa 10.0.0.13
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en1 Ifa 10.0.0.20
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.20 Ifp en1 Ifa 10.0.0.20
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.11
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.11 Ifp en0 Ifa 10.0.0.11
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 192.168.2.1 Ifp fw0 Ifa 192.168.2.30
  1. Dest 192.168.2.0 Mask 255.255.255.0 Gate 192.168.2.30 Ifp fw0 Ifa 192.168.2.30
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.19
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.19 Ifp en0 Ifa 10.0.0.19
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.12
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.12 Ifp en0 Ifa 10.0.0.12
 }
-
 Routes are <IPv4RouteList[6]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.10
  1. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en1 Ifa 10.0.0.20 [SCOPED]
@@ -87,7 +72,6 @@ Routes are <IPv4RouteList[6]> = {
  4. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.20 Ifp en1 Ifa 10.0.0.20 [SCOPED]
  5. Dest 192.168.2.0 Mask 255.255.255.0 Gate 192.168.2.30 Ifp fw0 Ifa 192.168.2.30
 }
-
 routes1 and routes2 are the same
 
 Starting test test2
@@ -95,32 +79,26 @@ test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.12
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.12 Ifp en0 Ifa 10.0.0.12
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 192.168.2.1 Ifp fw0 Ifa 192.168.2.30
  1. Dest 192.168.2.0 Mask 255.255.255.0 Gate 192.168.2.30 Ifp fw0 Ifa 192.168.2.30
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.11
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.11 Ifp en0 Ifa 10.0.0.11
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en1 Ifa 10.0.0.20
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.20 Ifp en1 Ifa 10.0.0.20
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.13
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.13 Ifp en0 Ifa 10.0.0.13
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.10
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.10 Ifp en0 Ifa 10.0.0.10
 }
-
 Routes are <IPv4RouteList[6]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.10
  1. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en1 Ifa 10.0.0.20 [SCOPED]
@@ -129,37 +107,30 @@ Routes are <IPv4RouteList[6]> = {
  4. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.20 Ifp en1 Ifa 10.0.0.20 [SCOPED]
  5. Dest 192.168.2.0 Mask 255.255.255.0 Gate 192.168.2.30 Ifp fw0 Ifa 192.168.2.30
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.10
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.10 Ifp en0 Ifa 10.0.0.10
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.13
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.13 Ifp en0 Ifa 10.0.0.13
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en1 Ifa 10.0.0.20
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.20 Ifp en1 Ifa 10.0.0.20
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.11
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.11 Ifp en0 Ifa 10.0.0.11
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 192.168.2.1 Ifp fw0 Ifa 192.168.2.30
  1. Dest 192.168.2.0 Mask 255.255.255.0 Gate 192.168.2.30 Ifp fw0 Ifa 192.168.2.30
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.12
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.12 Ifp en0 Ifa 10.0.0.12
 }
-
 Routes are <IPv4RouteList[6]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.10
  1. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en1 Ifa 10.0.0.20 [SCOPED]
@@ -168,7 +139,6 @@ Routes are <IPv4RouteList[6]> = {
  4. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.20 Ifp en1 Ifa 10.0.0.20 [SCOPED]
  5. Dest 192.168.2.0 Mask 255.255.255.0 Gate 192.168.2.30 Ifp fw0 Ifa 192.168.2.30
 }
-
 routes1 and routes2 are the same
 
 Starting test test3
@@ -176,27 +146,22 @@ test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 17.202.20.1 Ifp en0 Ifa 17.202.40.191 [non-local]
  1. Dest 17.202.40.0 Mask 255.255.252.0 Gate 17.202.40.191 Ifp en0 Ifa 17.202.40.191
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.12
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.12 Ifp en0 Ifa 10.0.0.12
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.11
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.11 Ifp en0 Ifa 10.0.0.11
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en1 Ifa 10.0.0.20
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.20 Ifp en1 Ifa 10.0.0.20
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 17.202.20.1 Ifp en1 Ifa 17.202.42.24 [non-local]
  1. Dest 17.202.40.0 Mask 255.255.252.0 Gate 17.202.42.24 Ifp en1 Ifa 17.202.42.24
 }
-
 Routes are <IPv4RouteList[6]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 17.202.20.1 Ifp en0 Ifa 17.202.40.191 [non-local]
  1. Dest 0.0.0.0 Mask 0.0.0.0 Gate 17.202.20.1 Ifp en1 Ifa 17.202.42.24 [non-local] [SCOPED]
@@ -205,32 +170,26 @@ Routes are <IPv4RouteList[6]> = {
  4. Dest 17.202.40.0 Mask 255.255.252.0 Gate 17.202.40.191 Ifp en0 Ifa 17.202.40.191
  5. Dest 17.202.40.0 Mask 255.255.252.0 Gate 17.202.42.24 Ifp en1 Ifa 17.202.42.24 [SCOPED]
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 17.202.20.1 Ifp en1 Ifa 17.202.42.24 [non-local]
  1. Dest 17.202.40.0 Mask 255.255.252.0 Gate 17.202.42.24 Ifp en1 Ifa 17.202.42.24
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en1 Ifa 10.0.0.20
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.20 Ifp en1 Ifa 10.0.0.20
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.11
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.11 Ifp en0 Ifa 10.0.0.11
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.12
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.12 Ifp en0 Ifa 10.0.0.12
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 17.202.20.1 Ifp en0 Ifa 17.202.40.191 [non-local]
  1. Dest 17.202.40.0 Mask 255.255.252.0 Gate 17.202.40.191 Ifp en0 Ifa 17.202.40.191
 }
-
 Routes are <IPv4RouteList[6]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 17.202.20.1 Ifp en0 Ifa 17.202.40.191 [non-local]
  1. Dest 0.0.0.0 Mask 0.0.0.0 Gate 17.202.20.1 Ifp en1 Ifa 17.202.42.24 [non-local] [SCOPED]
@@ -239,7 +198,6 @@ Routes are <IPv4RouteList[6]> = {
  4. Dest 17.202.40.0 Mask 255.255.252.0 Gate 17.202.40.191 Ifp en0 Ifa 17.202.40.191
  5. Dest 17.202.40.0 Mask 255.255.252.0 Gate 17.202.42.24 Ifp en1 Ifa 17.202.42.24 [SCOPED]
 }
-
 routes1 and routes2 are the same
 
 Starting test test4
@@ -247,27 +205,22 @@ test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 17.202.20.1 Ifp en0 Ifa 17.202.40.191 [non-local]
  1. Dest 17.202.40.0 Mask 255.255.252.0 Gate 17.202.40.191 Ifp en0 Ifa 17.202.40.191
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.12
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.12 Ifp en0 Ifa 10.0.0.12
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.11
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.11 Ifp en0 Ifa 10.0.0.11
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en1 Ifa 10.0.0.20
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.20 Ifp en1 Ifa 10.0.0.20
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 17.202.20.1 Ifp en1 Ifa 17.202.42.24 [non-local]
  1. Dest 17.202.40.0 Mask 255.255.252.0 Gate 17.202.42.24 Ifp en1 Ifa 17.202.42.24
 }
-
 Routes are <IPv4RouteList[6]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 17.202.20.1 Ifp en0 Ifa 17.202.40.191 [non-local]
  1. Dest 0.0.0.0 Mask 0.0.0.0 Gate 17.202.20.1 Ifp en1 Ifa 17.202.42.24 [non-local] [SCOPED]
@@ -276,32 +229,26 @@ Routes are <IPv4RouteList[6]> = {
  4. Dest 17.202.40.0 Mask 255.255.252.0 Gate 17.202.40.191 Ifp en0 Ifa 17.202.40.191
  5. Dest 17.202.40.0 Mask 255.255.252.0 Gate 17.202.42.24 Ifp en1 Ifa 17.202.42.24 [SCOPED]
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 17.202.20.1 Ifp en1 Ifa 17.202.42.24 [non-local]
  1. Dest 17.202.40.0 Mask 255.255.252.0 Gate 17.202.42.24 Ifp en1 Ifa 17.202.42.24
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en1 Ifa 10.0.0.20
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.20 Ifp en1 Ifa 10.0.0.20
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.11
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.11 Ifp en0 Ifa 10.0.0.11
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.12
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.12 Ifp en0 Ifa 10.0.0.12
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 17.202.20.1 Ifp en0 Ifa 17.202.40.191 [non-local]
  1. Dest 17.202.40.0 Mask 255.255.252.0 Gate 17.202.40.191 Ifp en0 Ifa 17.202.40.191
 }
-
 Routes are <IPv4RouteList[6]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 17.202.20.1 Ifp en0 Ifa 17.202.40.191 [non-local]
  1. Dest 0.0.0.0 Mask 0.0.0.0 Gate 17.202.20.1 Ifp en1 Ifa 17.202.42.24 [non-local] [SCOPED]
@@ -310,39 +257,32 @@ Routes are <IPv4RouteList[6]> = {
  4. Dest 17.202.40.0 Mask 255.255.252.0 Gate 17.202.40.191 Ifp en0 Ifa 17.202.40.191
  5. Dest 17.202.40.0 Mask 255.255.252.0 Gate 17.202.42.24 Ifp en1 Ifa 17.202.42.24 [SCOPED]
 }
-
 routes1 and routes2 are the same
 
 Starting test test5
 test: Adding <IPv4RouteList[1]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 17.219.156.1 Ifp ppp0 Ifa 17.219.156.22
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 17.202.20.1 Ifp en0 Ifa 17.202.40.191 [non-local]
  1. Dest 17.202.40.0 Mask 255.255.252.0 Gate 17.202.40.191 Ifp en0 Ifa 17.202.40.191
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.12
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.12 Ifp en0 Ifa 10.0.0.12
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.11
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.11 Ifp en0 Ifa 10.0.0.11
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en1 Ifa 10.0.0.20
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.20 Ifp en1 Ifa 10.0.0.20
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 17.202.20.1 Ifp en1 Ifa 17.202.42.24 [non-local]
  1. Dest 17.202.40.0 Mask 255.255.252.0 Gate 17.202.42.24 Ifp en1 Ifa 17.202.42.24
 }
-
 Routes are <IPv4RouteList[7]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 17.219.156.1 Ifp ppp0 Ifa 17.219.156.22
  1. Dest 0.0.0.0 Mask 0.0.0.0 Gate 17.202.20.1 Ifp en0 Ifa 17.202.40.191 [non-local] [SCOPED]
@@ -352,36 +292,29 @@ Routes are <IPv4RouteList[7]> = {
  5. Dest 17.202.40.0 Mask 255.255.252.0 Gate 17.202.40.191 Ifp en0 Ifa 17.202.40.191
  6. Dest 17.202.40.0 Mask 255.255.252.0 Gate 17.202.42.24 Ifp en1 Ifa 17.202.42.24 [SCOPED]
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 17.202.20.1 Ifp en1 Ifa 17.202.42.24 [non-local]
  1. Dest 17.202.40.0 Mask 255.255.252.0 Gate 17.202.42.24 Ifp en1 Ifa 17.202.42.24
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en1 Ifa 10.0.0.20
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.20 Ifp en1 Ifa 10.0.0.20
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.11
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.11 Ifp en0 Ifa 10.0.0.11
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.12
  1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.12 Ifp en0 Ifa 10.0.0.12
 }
-
 test: Adding <IPv4RouteList[2]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 17.202.20.1 Ifp en0 Ifa 17.202.40.191 [non-local]
  1. Dest 17.202.40.0 Mask 255.255.252.0 Gate 17.202.40.191 Ifp en0 Ifa 17.202.40.191
 }
-
 test: Adding <IPv4RouteList[1]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 17.219.156.1 Ifp ppp0 Ifa 17.219.156.22
 }
-
 Routes are <IPv4RouteList[7]> = {
  0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 17.219.156.1 Ifp ppp0 Ifa 17.219.156.22
  1. Dest 0.0.0.0 Mask 0.0.0.0 Gate 17.202.20.1 Ifp en0 Ifa 17.202.40.191 [non-local] [SCOPED]
@@ -391,7 +324,21 @@ Routes are <IPv4RouteList[7]> = {
  5. Dest 17.202.40.0 Mask 255.255.252.0 Gate 17.202.40.191 Ifp en0 Ifa 17.202.40.191
  6. Dest 17.202.40.0 Mask 255.255.252.0 Gate 17.202.42.24 Ifp en1 Ifa 17.202.42.24 [SCOPED]
 }
+routes1 and routes2 are the same
 
+Starting test test15
+test: Adding <IPv4RouteList[1]> = {
+ 0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 169.254.22.44 Ifp en0 Ifa 169.254.22.44 [direct] [never] [SCOPED]
+}
+Routes are <IPv4RouteList[1]> = {
+ 0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 169.254.22.44 Ifp en0 Ifa 169.254.22.44 [direct] [SCOPED]
+}
+test: Adding <IPv4RouteList[1]> = {
+ 0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 169.254.22.44 Ifp en0 Ifa 169.254.22.44 [direct] [never] [SCOPED]
+}
+Routes are <IPv4RouteList[1]> = {
+ 0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 169.254.22.44 Ifp en0 Ifa 169.254.22.44 [direct] [SCOPED]
+}
 routes1 and routes2 are the same
 
 Compare 1 to 2:
@@ -765,4 +712,17 @@ Remove old[0] = Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.10
 Remove old[2] = Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.10 Ifp en0 Ifa 10.0.0.10
 
 Checking for leaks
+Process:         test_ipv4_routelist [XXXX]
+Path: XXXX
+Load Address:    0xXXXX
+Identifier:      test_ipv4_routelist
+Version:         ??? (???)
+Code Type:       X86-64 (Native)
+Parent Process:  sh [XXXX]
+
+Date/Time:       XXXX
+OS Version: XXXX
+Report Version:  7
+
+leaks Report Version:  2.0
 Process XXXX 0 leaks for 0 total leaked bytes.
index c4df41f9279b4665f04ea4a4502964a3c525262b..b21ea5e1bfb2bfa4d5b82ccc11d9b19915ca2327 100644 (file)
@@ -11,7 +11,7 @@ cleanup()
     exit 1
 }
 
-trap cleanup 1 2 3 15 
+trap cleanup 1 2 3 15
 
 run_program()
 {
@@ -84,4 +84,4 @@ else
     usage "${0}"
 fi
 
-exit 0
\ No newline at end of file
+exit 0
index bd0a96004c83f6cb0dce1ce82bdeb02b19bf54c1..7e483e35797167523369ffbf682efdd76a17dbb7 100644 (file)
        <key>CFBundlePackageType</key>
        <string>BNDL</string>
        <key>CFBundleShortVersionString</key>
-       <string>1.12.2</string>
+       <string>1.13</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>1.12.2</string>
+       <string>1.13</string>
 </dict>
 </plist>
index 639f9aea694f6810020688567b5115e3aa9dec23..4ba2a566aa47165431e3135bd93e3ad733e0e30b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001-2012 Apple Inc. All rights reserved.
+ * Copyright (c) 2001-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #include <unistd.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <sys/sockio.h>
 #include <sys/stat.h>
 #include <sys/sysctl.h>
 #include <sys/param.h>
 #include <mach/mach.h>
 #include <net/ethernet.h>
-#include <net/if.h>
 #include <net/if_types.h>
 #include <pthread.h>
 #include <vproc.h>
@@ -590,6 +587,40 @@ updateVirtualNetworkInterfaceConfiguration(SCPreferencesRef                prefs,
     return;
 }
 
+#if    !TARGET_OS_EMBEDDED
+
+#define        BT_PAN_NAME "Bluetooth PAN"
+
+static void
+updateBTPANInformation(const void *value, void *context)
+{   CFDictionaryRef dict    = (CFDictionaryRef)value;
+    CFStringRef            if_name;
+    CFDictionaryRef info;
+    CFStringRef            name;
+
+    if_name = CFDictionaryGetValue(dict, CFSTR(kIOBSDNameKey));
+    if (!isA_CFString(if_name)) {
+       // if no BSD name
+       return;
+    }
+
+    info = CFDictionaryGetValue(dict, CFSTR(kSCNetworkInterfaceInfo));
+    if (!isA_CFDictionary(info)) {
+       // if no SCNetworkInterface info
+       return;
+    }
+
+    name = CFDictionaryGetValue(info, kSCPropUserDefinedName);
+    if (!isA_CFString(name) || !CFEqual(name, CFSTR(BT_PAN_NAME))) {
+       // if not BT-PAN interface
+       return;
+    }
+
+    CFDictionaryAddValue(S_state, CFSTR("_" BT_PAN_NAME "_"), if_name);
+    return;
+}
+#endif // !TARGET_OS_EMBEDDED
+
 static CFDictionaryRef
 createInterfaceDict(SCNetworkInterfaceRef interface)
 {
@@ -612,6 +643,11 @@ createInterfaceDict(SCNetworkInterfaceRef interface)
        CFDictionarySetValue(new_if, CFSTR(kIOPathMatchKey), val);
     }
 
+    val = _SCNetworkInterfaceGetIOInterfaceNamePrefix(interface);
+    if (val != NULL) {
+       CFDictionarySetValue(new_if, CFSTR(kIOInterfaceNamePrefix), val);
+    }
+
     val = _SCNetworkInterfaceGetIOInterfaceType(interface);
     if (val != NULL) {
        CFDictionarySetValue(new_if, CFSTR(kIOInterfaceType), val);
@@ -767,8 +803,8 @@ matchInterfaceInfo(CFDictionaryRef known_info, CFDictionaryRef match_info)
        known_info = thinInterfaceInfo(known_info);
        match_info = thinInterfaceInfo(match_info);
        match = _SC_CFEqual(known_info, match_info);
-       CFRelease(known_info);
-       CFRelease(match_info);
+       if (known_info != NULL) CFRelease(known_info);
+       if (match_info != NULL) CFRelease(match_info);
     }
 
     return match;
@@ -873,6 +909,83 @@ matchUnnamed(const void *value, void *context)
     return;
 }
 
+static Boolean
+interfaceExists(CFStringRef prefix, CFNumberRef unit)
+{
+    Boolean            found       = FALSE;
+    CFDictionaryRef    match_dict;
+    CFStringRef                match_keys[2];
+    CFTypeRef          match_vals[2];
+    CFDictionaryRef    matching;
+
+
+
+    io_registry_entry_t        entry           = MACH_PORT_NULL;
+    io_iterator_t              iterator        = MACH_PORT_NULL;
+    kern_return_t              kr;
+    mach_port_t                        masterPort      = MACH_PORT_NULL;
+
+    kr = IOMasterPort(bootstrap_port, &masterPort);
+    if (kr != KERN_SUCCESS) {
+       SCLog(TRUE, LOG_ERR,
+             CFSTR(MY_PLUGIN_NAME ": IOMasterPort returned 0x%x"),
+             kr);
+       goto error;
+    }
+
+    // look for kIONetworkInterface with matching prefix and unit
+    match_keys[0] = CFSTR(kIOInterfaceNamePrefix);
+    match_vals[0] = prefix;
+    match_keys[1] = CFSTR(kIOInterfaceUnit);
+    match_vals[1] = unit;
+    match_dict = CFDictionaryCreate(NULL,
+                                   (const void **)match_keys,
+                                   (const void **)match_vals,
+                                   2,
+                                   &kCFTypeDictionaryKeyCallBacks,
+                                   &kCFTypeDictionaryValueCallBacks);
+
+    match_keys[0] = CFSTR(kIOProviderClassKey);
+    match_vals[0] = CFSTR(kIONetworkInterfaceClass);
+    match_keys[1] = CFSTR(kIOPropertyMatchKey);
+    match_vals[1] = match_dict;
+    matching = CFDictionaryCreate(NULL,
+                                 (const void **)match_keys,
+                                 (const void **)match_vals,
+                                 sizeof(match_keys)/sizeof(match_keys[0]),
+                                 &kCFTypeDictionaryKeyCallBacks,
+                                 &kCFTypeDictionaryValueCallBacks);
+    CFRelease(match_dict);
+
+    // note: the "matching" dictionary will be consumed by the following
+    kr = IOServiceGetMatchingServices(masterPort, matching, &iterator);
+    if ((kr != kIOReturnSuccess) || (iterator == MACH_PORT_NULL)) {
+       // if no interface
+       goto error;
+    }
+
+    entry = IOIteratorNext(iterator);
+    if (entry == MACH_PORT_NULL) {
+       // if no interface
+       goto error;
+    }
+
+    found = TRUE;
+
+error:
+    if (masterPort != MACH_PORT_NULL) {
+       mach_port_deallocate(mach_task_self(), masterPort);
+    }
+    if (entry != MACH_PORT_NULL) {
+       IOObjectRelease(entry);
+    }
+    if (iterator != MACH_PORT_NULL) {
+       IOObjectRelease(iterator);
+    }
+
+    return (found);
+}
+
 /*
  * lookupMatchingInterface
  *
@@ -908,8 +1021,8 @@ lookupMatchingInterface(SCNetworkInterfaceRef      interface,
     match_context.match_builtin        = builtin;
     match_context.matches      = NULL;
 
-    // check for matches to already named interfaces
-    // ... and appends each match that we find to match_context.matches
+    // check for matches to interfaces that have already been named
+    // ... and append each match that we find to match_context.matches
     if (db_list != NULL) {
        CFArrayApplyFunction(db_list,
                             CFRangeMake(0, CFArrayGetCount(db_list)),
@@ -917,8 +1030,8 @@ lookupMatchingInterface(SCNetworkInterfaceRef      interface,
                             &match_context);
     }
 
-    // check for matches to to be named interfaces
-    // ... and CFReleases match_context.matches if we find another network
+    // check for matches to interfaces that will be named
+    // ... and CFRelease match_context.matches if we find another network
     //     interface of the same type that also needs to be named
     if (if_list != NULL) {
        CFIndex    if_list_count;
@@ -946,18 +1059,15 @@ lookupMatchingInterface(SCNetworkInterfaceRef    interface,
 
        name = CFDictionaryGetValue(match, CFSTR(kIOBSDNameKey));
        if (isA_CFString(name)) {
-           int         sock;
+           CFStringRef     prefix;
+           CFNumberRef     unit;
 
-           sock = socket(AF_INET, SOCK_DGRAM, 0);
-           if (sock != -1) {
-               struct ifreq    ifr;
-
-               (void)_SC_cfstring_to_cstring(name, ifr.ifr_name, sizeof(ifr.ifr_name), kCFStringEncodingASCII);
-               if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) {
-                   // if interface name not currently in-use
+           prefix = CFDictionaryGetValue(match, CFSTR(kIOInterfaceNamePrefix));
+           unit   = CFDictionaryGetValue(match, CFSTR(kIOInterfaceUnit));
+           if (isA_CFString(prefix) && isA_CFNumber(unit)) {
+               if (!interfaceExists(prefix, unit)) {
                    active = FALSE;
                }
-               close(sock);
            }
        }
 
@@ -1013,6 +1123,11 @@ insertInterface(CFMutableArrayRef db_list, SCNetworkInterfaceRef interface)
     }
 
     CFArrayAppendValue(S_dblist, if_dict);
+
+#if    !TARGET_OS_EMBEDDED
+    updateBTPANInformation(if_dict, NULL);
+#endif // !TARGET_OS_EMBEDDED
+
     CFRelease(if_dict);
     return;
 }
@@ -1179,7 +1294,6 @@ copyInterfaceForIORegistryEntryID(uint64_t entryID)
        IOObjectRelease(iterator);
     }
     return (interface);
-
 }
 
 static SCNetworkInterfaceRef
@@ -1295,6 +1409,47 @@ displayInterface(SCNetworkInterfaceRef interface)
          addr);
 }
 
+static Boolean
+builtinAvailable(SCNetworkInterfaceRef interface,      // new interface
+                CFNumberRef            if_unit)        // desired unit
+{
+    CFIndex    i;
+    CFNumberRef if_type        = _SCNetworkInterfaceGetIOInterfaceType(interface);
+    CFIndex    n;
+
+    n = (S_dblist != NULL) ? CFArrayGetCount(S_dblist) : 0;
+    for (i = 0; i < n; i++) {
+       CFStringRef         if_path;
+       CFDictionaryRef     known_dict      = CFArrayGetValueAtIndex(S_dblist, i);
+       CFStringRef         known_path;
+       CFNumberRef         known_type;
+       CFNumberRef         known_unit;
+
+       known_type = CFDictionaryGetValue(known_dict, CFSTR(kIOInterfaceType));
+       if (!_SC_CFEqual(if_type, known_type)) {
+           continue;   // if not the same interface type
+       }
+
+       known_unit = CFDictionaryGetValue(known_dict, CFSTR(kIOInterfaceUnit));
+       if (!_SC_CFEqual(if_unit, known_unit)) {
+           continue;   // if not the same interface unit
+       }
+
+       if_path    = _SCNetworkInterfaceGetIOPath(interface);
+       known_path = CFDictionaryGetValue(known_dict, CFSTR(kIOPathMatchKey));
+       if (!_SC_CFEqual(if_path, known_path)) {
+           // if different IORegistry path
+           return FALSE;
+       }
+
+       // if same type, same unit, same path
+       return TRUE;
+    }
+
+    // if interface type/unit not found
+    return TRUE;
+}
+
 static int
 builtinCount(CFArrayRef if_list, CFIndex last, CFNumberRef if_type)
 {
@@ -1418,10 +1573,31 @@ nameInterfaces(CFMutableArrayRef if_list)
                int             next_unit       = 0;
 
                if (is_builtin) {
-                   // built-in interface, use the reserved slots
+                   // built-in interface, try to use the reserved slots
                    next_unit = builtinCount(if_list, i, type);
-               } else {
-                   // not built-in, skip over the reserved slots
+
+                   // But, before claiming a reserved slot we check to see if the
+                   // slot had previously been used.  If so, and if the slot had been
+                   // assigned to the same type of interface, then we will perform a
+                   // replacement (e.g. assume that this was a board swap).  But, if
+                   // the new interface is a different type then we assume that the
+                   // built-in configuration has changed and allocate a new unit from
+                   // the non-reserved slots.
+
+                   unit = CFNumberCreate(NULL, kCFNumberIntType, &next_unit);
+                   if (!builtinAvailable(interface, unit)) {
+                       // if [built-in] unit not available
+                       SCLog(S_debug, LOG_INFO,
+                             CFSTR(MY_PLUGIN_NAME ": Interface not assigned [built-in] unit %@"),
+                             unit);
+                       CFRelease(unit);
+                       unit = NULL;
+                   }
+               }
+
+               if (unit == NULL) {
+                   // not built-in (or built-in unit not available), allocate from
+                   // the non-reserved slots
                    next_unit = builtinCount(if_list, n, type);
 
                    unit = getHighestUnitForType(type);
@@ -1433,8 +1609,9 @@ nameInterfaces(CFMutableArrayRef if_list)
                            next_unit = high_unit + 1;
                        }
                    }
+
+                   unit = CFNumberCreate(NULL, kCFNumberIntType, &next_unit);
                }
-               unit = CFNumberCreate(NULL, kCFNumberIntType, &next_unit);
 
                SCLog(S_debug, LOG_INFO,
                      CFSTR(MY_PLUGIN_NAME ": Interface assigned unit %@ (%s)"),
@@ -1563,6 +1740,73 @@ nameInterfaces(CFMutableArrayRef if_list)
     return;
 }
 
+#if    !TARGET_OS_IPHONE
+static void
+updateNetworkConfiguration(CFArrayRef if_list)
+{
+    Boolean            do_commit       = FALSE;
+    CFIndex            i;
+    CFIndex            n;
+    SCPreferencesRef   prefs           = NULL;
+    SCNetworkSetRef    set             = NULL;
+
+    prefs = SCPreferencesCreate(NULL, CFSTR("SCMonitor"), NULL);
+
+    set = SCNetworkSetCopyCurrent(prefs);
+    if (set == NULL) {
+       SCLog(TRUE, LOG_ERR, CFSTR(MY_PLUGIN_NAME ": No current set"));
+       goto done;
+    }
+
+    n = CFArrayGetCount(if_list);
+    for (i = 0; i < n; i++) {
+       SCNetworkInterfaceRef   interface;
+
+       interface = CFArrayGetValueAtIndex(if_list, i);
+       if (SCNetworkSetEstablishDefaultInterfaceConfiguration(set, interface)) {
+           SCLog(TRUE, LOG_INFO,
+                 CFSTR(MY_PLUGIN_NAME ": adding default configuration for %s"),
+                 SCNetworkInterfaceGetBSDName(interface));
+           do_commit = TRUE;
+       }
+    }
+
+    if (do_commit) {
+       Boolean ok;
+
+       ok = SCPreferencesCommitChanges(prefs);
+       if (!ok) {
+           SCLog(TRUE, LOG_INFO,
+                 CFSTR(MY_PLUGIN_NAME ": updateNetworkConfiguration: SCPreferencesCommitChanges() failed: %s"),
+                 SCErrorString(SCError()));
+           goto done;
+       }
+
+       ok = SCPreferencesApplyChanges(prefs);
+       if (!ok) {
+           SCLog(TRUE, LOG_INFO,
+                 CFSTR(MY_PLUGIN_NAME ": updateNetworkConfiguration: SCPreferencesApplyChanges() failed: %s"),
+                 SCErrorString(SCError()));
+           goto done;
+       }
+    }
+
+  done :
+
+    if (set != NULL) {
+       CFRelease(set);
+       set = NULL;
+    }
+
+    if (prefs != NULL) {
+       CFRelease(prefs);
+       prefs = NULL;
+    }
+
+    return;
+}
+#endif // !TARGET_OS_IPHONE
+
 static void
 updateInterfaces()
 {
@@ -1592,6 +1836,19 @@ updateInterfaces()
         */
        writeInterfaceList(S_dblist);
        updateVirtualNetworkInterfaceConfiguration(NULL, kSCPreferencesNotificationApply, NULL);
+
+#if    !TARGET_OS_IPHONE
+       if (access("/usr/libexec/UserEventAgent",  X_OK) == -1
+           && errno == ENOENT) {
+           /*
+            * We are most likely booted into the Recovery OS with no "SCMonitor"
+            * UserEventAgent plugin running so let's make sure we update the
+            * network configuration for new interfaces.
+            */
+           updateNetworkConfiguration(S_iflist);
+       }
+#endif // !TARGET_OS_IPHONE
+
        updateStore();
 
        if (S_iflist != NULL) {
@@ -1961,6 +2218,7 @@ iterateRegistryBusy(io_iterator_t iterator, CFArrayRef nodes, CFMutableStringRef
        } else {
            newNodes = CFArrayCreateMutableCopy(NULL, 0, nodes);
        }
+       assert(newNodes != NULL);
 
        kr = IORegistryEntryGetName(obj, name);
        if (kr != kIOReturnSuccess) {
@@ -2257,6 +2515,16 @@ setup_IOKit(CFBundleRef bundle)
     }
 #endif /* WAIT_PREVIOUS_BOOT_INTERFACES_OR_QUIET */
 
+#if    !TARGET_OS_EMBEDDED
+    if (S_dblist != NULL) {
+       // apply special handling for the BT-PAN interface (if present)
+       CFArrayApplyFunction(S_dblist,
+                            CFRangeMake(0, CFArrayGetCount(S_dblist)),
+                            updateBTPANInformation,
+                            NULL);
+    }
+#endif // !TARGET_OS_EMBEDDED
+
     ok = TRUE;
 
  done:
index dd4142696bb100a74efef3774347841ae718d3fd..a138cb79ec5bac8d190f180483bc00fd2a568ab0 100644 (file)
        <key>CFBundlePackageType</key>
        <string>BNDL</string>
        <key>CFBundleShortVersionString</key>
-       <string>1.12.2</string>
+       <string>1.13</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>1.12.2</string>
+       <string>1.13</string>
        <key>Requires</key>
        <array>
                <string>com.apple.SystemConfiguration.InterfaceNamer</string>
index 0830019a5a1e1c3516d43adaf662f589e387223b..364fd6db4fecd7d9af813835f7cc0d0c6344a862 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2006, 2009, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2002-2006, 2009, 2011, 2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -189,6 +189,66 @@ done:
 #endif /* KEV_DL_LINK_QUALITY_METRIC_CHANGED */
 
 
+#ifdef KEV_DL_ISSUES
+static CFStringRef
+create_link_issues_key(const char * if_name)
+{
+       CFStringRef     interface;
+       CFStringRef     key;
+
+       interface = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingMacRoman);
+       key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+                                                           kSCDynamicStoreDomainState,
+                                                           interface,
+                                                           kSCEntNetLinkIssues);
+       CFRelease(interface);
+       return (key);
+}
+
+
+__private_extern__
+void
+interface_update_link_issues(const char                *if_name,
+                            uint64_t           timestamp,
+                            uint8_t            *modid,
+                            size_t             modid_size,
+                            uint8_t            *info,
+                            size_t             info_size)
+{
+       CFDataRef               infoData;
+       CFStringRef             key;
+       CFDataRef               modidData;
+       CFMutableDictionaryRef  newDict;
+       CFDateRef               timeStamp;
+
+       key = create_link_issues_key(if_name);
+
+       newDict = copy_entity(key);
+
+       modidData = CFDataCreate(NULL, modid, modid_size);
+       CFDictionarySetValue(newDict, kSCPropNetLinkIssuesModuleID, modidData);
+       CFRelease(modidData);
+
+       if (info_size != 0) {
+               infoData = CFDataCreate(NULL, info, info_size);
+               CFDictionarySetValue(newDict, kSCPropNetLinkIssuesInfo, infoData);
+               CFRelease(infoData);
+       } else {
+               CFDictionaryRemoveValue(newDict, kSCPropNetLinkIssuesInfo);
+       }
+
+       timeStamp = CFDateCreate(NULL, timestamp);
+       CFDictionarySetValue(newDict, kSCPropNetLinkIssuesTimeStamp, timeStamp);
+       CFRelease(timeStamp);
+
+       cache_SCDynamicStoreSetValue(store, key, newDict);
+       CFRelease(newDict);
+       CFRelease(key);
+       return;
+}
+#endif /* KEV_DL_ISSUES */
+
+
 __private_extern__
 void
 interface_detaching(const char *if_name)
@@ -206,6 +266,7 @@ interface_detaching(const char *if_name)
        return;
 }
 
+
 static void
 interface_remove(const char *if_name)
 {
@@ -215,11 +276,17 @@ interface_remove(const char *if_name)
        cache_SCDynamicStoreRemoveValue(store, key);
        CFRelease(key);
 
-#ifdef KEV_DL_LINK_QUALITY_METRIC_CHANGED
+#ifdef KEV_DL_LINK_QUALITY_METRIC_CHANGED
        key = create_linkquality_key(if_name);
        cache_SCDynamicStoreRemoveValue(store, key);
        CFRelease(key);
-#endif /* KEV_DL_LINK_QUALITY_METRIC_CHANGED */
+#endif /* KEV_DL_LINK_QUALITY_METRIC_CHANGED */
+
+#ifdef KEV_DL_ISSUES
+       key = create_link_issues_key(if_name);
+       cache_SCDynamicStoreRemoveValue(store, key);
+       CFRelease(key);
+#endif /* KEV_DL_ISSUES */
 
        return;
 }
@@ -269,7 +336,6 @@ link_update_status(const char *if_name, boolean_t attach)
        return;
 }
 
-
 __private_extern__
 void
 link_add(const char *if_name)
index f78ce84634512c685d42912f83873b152ad6eb64..ae3b00128161e4f7a27f56c507b3797c9a060d1b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2004, 2005, 2011 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2002, 2004, 2005, 2011-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 
 __BEGIN_DECLS
 
-__private_extern__
 void   interface_detaching             (const char *if_name);
 
-__private_extern__
 void   interface_update_idle_state     (const char *if_name);
 
-__private_extern__
+void   interface_update_link_issues    (const char     *if_name,
+                                        uint64_t       timestamp,
+                                        uint8_t        *modid,
+                                        size_t         modid_size,
+                                        uint8_t        *info,
+                                        size_t         info_size);
+
 void   interface_update_quality_metric (const char *if_name, int quality);
 
-__private_extern__
 void   link_add                        (const char *if_name);
 
-__private_extern__
 void   link_remove                     (const char *if_name);
 
-__private_extern__
 void   link_update_status              (const char *if_name, boolean_t attach);
 
 __END_DECLS
index 0e75b21a4b567c0f54bd342b5f29e4834a6c56bb..241d41f4218b14085c8c62b4166f41cb185e1b87 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2005, 2007, 2008, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2002-2005, 2007, 2008, 2011, 2012 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 
 __BEGIN_DECLS
 
-__private_extern__
 void   interface_update_ipv4   (struct ifaddrs *ifap, const char *if_name);
 
-__private_extern__
 void   interface_collision_ipv4(const char *if_name,
                                 struct in_addr ip_addr,
                                 int hw_len, const void * hw_addr);
 
 #if    !TARGET_OS_IPHONE
-__private_extern__
 void   port_in_use_ipv4        (uint16_t port, pid_t req_pid);
 #endif /* !TARGET_OS_IPHONE */
 
index abe37ff59596d268511764080e4e9623cc9787b2..f30d3a70d9985c85fee29451ac968bb620868c14 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2007, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2002-2007, 2011, 2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -344,7 +344,8 @@ interface_update_ipv6(struct ifaddrs *ifap, const char *if_name)
                appendFlags    (newDict, flags6);
 
 
-               if (ifa->ifa_flags & IFF_POINTOPOINT) {
+               if (ifa->ifa_flags & IFF_POINTOPOINT
+                   && ifa->ifa_dstaddr != NULL) {
                        struct sockaddr_in6     *dst6;
 
                        /* ALIGN: ifa should be aligned (from getifaddrs), cast ok. */
index 4cdd37803f673e98ba3b74785c07b82a3883e3d1..a00925524b46effe3ebd4cdaa2dd23028175b320 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2004, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2002, 2004, 2011, 2012 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -36,7 +36,6 @@
 
 __BEGIN_DECLS
 
-__private_extern__
 void   interface_update_ipv6   (struct ifaddrs *ifap, const char *if_name);
 
 __END_DECLS
index c2cad274232cbc7d19cd99bfdd07c86709d001c3..231b763d2d536a946c93f9474341e97a41416cf6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2008, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2008, 2010-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -103,6 +103,18 @@ static const char *dlEventName[] = {
 #ifdef  KEV_DL_LINK_QUALITY_METRIC_CHANGED
        "KEV_DL_LINK_QUALITY_METRIC_CHANGED",
 #endif
+#ifdef KEV_DL_NODE_PRESENCE
+       "KEV_DL_NODE_PRESENCE"
+#endif
+#ifdef KEV_DL_NODE_ABSENCE
+       "KEV_DL_NODE_ABSENCE"
+#endif
+#ifdef KEV_DL_MASTER_ELECTED
+       "KEV_DL_MASTER_ELECTED"
+#endif
+#ifdef KEV_DL_ISSUES
+       "KEV_DL_ISSUES",
+#endif
 };
 
 static const char *inet6EventName[] = {
@@ -191,7 +203,7 @@ post_network_changed(void)
        if (network_changed) {
                uint32_t        status;
 
-               status = notify_post("com.apple.system.config.network_change");
+               status = notify_post(_SC_NOTIFY_NETWORK_CHANGE);
                if (status != NOTIFY_STATUS_OK) {
                        SCLog(TRUE, LOG_ERR, CFSTR("notify_post() failed: error=%ld"), status);
                }
@@ -260,6 +272,8 @@ copy_if_name(struct net_event_data * ev, char * ifr_name, int ifr_len)
        return;
 }
 
+static uint8_t info_zero[DLIL_MODARGLEN];
+
 static void
 processEvent_Apple_Network(struct kern_event_msg *ev_msg)
 {
@@ -455,6 +469,28 @@ processEvent_Apple_Network(struct kern_event_msg *ev_msg)
                                }
 #endif  // KEV_DL_LINK_QUALITY_METRIC_CHANGED
 
+#ifdef KEV_DL_ISSUES
+                               case KEV_DL_ISSUES: {
+                                       struct kev_dl_issues *issues;
+
+                                       issues = (struct kev_dl_issues *)event_data;
+                                       if (dataLen < sizeof(*ev)) {
+                                               handled = FALSE;
+                                               break;
+                                       }
+                                       copy_if_name(ev, ifr_name, sizeof(ifr_name));
+                                       interface_update_link_issues(ifr_name,
+                                                                    issues->timestamp,
+                                                                    issues->modid,
+                                                                    DLIL_MODIDLEN,
+                                                                    issues->info,
+                                                                    (bcmp(issues->info, info_zero, DLIL_MODIDLEN) != 0)
+                                                                       ?DLIL_MODARGLEN
+                                                                       :0);
+                                       break;
+                               }
+#endif // KEV_DL_ISSUES
+
                                case KEV_DL_SIFFLAGS :
                                case KEV_DL_SIFMETRICS :
                                case KEV_DL_SIFMTU :
index af70ff1dbcf05ccebf7ab2f13f2d3f93ac25bed0..9bce032d29678a3bf3fefe52887f47325111f843 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2004, 2005, 2007, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2002, 2004, 2005, 2007, 2011, 2012 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -63,7 +63,6 @@ extern Boolean                        _verbose;
 
 __BEGIN_DECLS
 
-__private_extern__
 int    dgram_socket            (int    domain);
 
 __END_DECLS
index 788c103b2e7c99cafc20a47b03c39198235d0f29..ebb5b271dbb64384f1207afa775ac8b3cdef80c5 100644 (file)
        <key>CFBundlePackageType</key>
        <string>BNDL</string>
        <key>CFBundleShortVersionString</key>
-       <string>1.12.2</string>
+       <string>1.13</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>1.12.2</string>
+       <string>1.13</string>
        <key>Requires</key>
        <array>
                <string>com.apple.SystemConfiguration.InterfaceNamer</string>
index 619bac49946b98cc191674b41f1f55a739309711..aa11307f7216f14e638b2c1efd4708b5f379bb86 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2007, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2002-2007, 2011, 2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -40,7 +40,6 @@
 #include <SystemConfiguration/SystemConfiguration.h>
 #include <SystemConfiguration/SCPrivate.h>
 #include <SystemConfiguration/SCValidation.h>
-#include <SystemConfiguration/LinkConfiguration.h>
 #include <SystemConfiguration/SCDPlugin.h>             // for _SCDPluginExecCommand
 
 #include "SCNetworkConfigurationInternal.h"
@@ -785,7 +784,7 @@ main(int argc, char **argv)
                                        service = CFArrayGetValueAtIndex(services, i);
                                        interface = SCNetworkServiceGetInterface(service);
                                        if ((interface != NULL) &&
-                                           !CFSetContainsValue(seen, interface)){
+                                           !CFSetContainsValue(seen, interface)) {
                                                CFDictionaryRef capabilities;
 
                                                capabilities = SCNetworkInterfaceCopyCapability(interface, NULL);
index 55b61a52c98708076ca6d288932c2e83fcc2056f..7963f2da6d4bbf3c3855d15b3b0a2cd76bb71141 100644 (file)
        <key>CFBundlePackageType</key>
        <string>BNDL</string>
        <key>CFBundleShortVersionString</key>
-       <string>1.12.2</string>
+       <string>1.13</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>1.12.2</string>
+       <string>1.13</string>
        <key>Enabled</key>
        <false/>
        <key>Verbose</key>
index be89fdead1181da0815ef118e94bf0aa4ce904ef..3a86ea740a6357f60108f012a5eb585b04adff63 100644 (file)
        <key>CFBundlePackageType</key>
        <string>BNDL</string>
        <key>CFBundleShortVersionString</key>
-       <string>1.12.2</string>
+       <string>1.13</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>1.12.2</string>
+       <string>1.13</string>
        <key>Enabled</key>
        <false/>
        <key>Verbose</key>
index 81b7c6ee446e9c5fc886ce3cdc1c05145dbfa8cc..ff5ea319e2d78eebaceb5b506e0975ea2b42f0cf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2005-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -1259,7 +1259,7 @@ console_notification(SCDynamicStoreRef store, CFArrayRef changedKeys, void *cont
                        sessionUserName  = CFDictionaryGetValue(session, kSCConsoleSessionUserName);
                        sessionOnConsole = CFDictionaryGetValue(session, kSCConsoleSessionOnConsole);
 
-                       CFStringAppendFormat(str, NULL, CFSTR("\n%d : id=%@, user=%@, console=%s"),
+                       CFStringAppendFormat(str, NULL, CFSTR("\n%ld : id=%@, user=%@, console=%s"),
                                             i,
                                             sessionID,
                                             sessionUserName  != NULL ? sessionUserName : CFSTR("?"),
@@ -1512,8 +1512,6 @@ add_nwi_notification()
 #pragma mark Network Configuration Change Events
 
 
-#define        NETWORKCHANGED_NOTIFY_KEY       "com.apple.system.config.network_change"
-
 static void
 network_notification(CFMachPortRef port, void *msg, CFIndex size, void *info)
 {
@@ -1534,7 +1532,7 @@ add_network_notification()
        CFRunLoopSourceRef      rls;
        uint32_t                status;
 
-       status = notify_register_mach_port(NETWORKCHANGED_NOTIFY_KEY,
+       status = notify_register_mach_port(_SC_NOTIFY_NETWORK_CHANGE,
                                           &notify_port,
                                           0,
                                           &notify_token);
index 4648c9d2106631aac0de061bfe52fbb2a3d646eb..f7ba56307c137ab7061a74473689d835ab4d127c 100644 (file)
        <key>CFBundlePackageType</key>
        <string>BNDL</string>
        <key>CFBundleShortVersionString</key>
-       <string>1.12.2</string>
+       <string>1.13</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>1.12.2</string>
+       <string>1.13</string>
        <key>Builtin</key>
        <true/>
        <key>Requires</key>
index 0200299eb35e2024525e36343d96a3ed317de29d..d11aa6deb170a066758f5045cceacd9f19233200 100644 (file)
@@ -135,7 +135,11 @@ establishNewPreferences()
                                        new_key = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@:%@"),
                                                                           old_model, existing_key);
                                        SCPreferencesSetValue(prefs, new_key, value);
-                                       SCPreferencesRemoveValue(prefs, existing_key);
+                                       
+                                       /* Let's preserve existing host names */
+                                       if (!CFEqual(existing_key, kSCPrefSystem)) {
+                                               SCPreferencesRemoveValue(prefs, existing_key);
+                                       }
                                        CFRelease(new_key);
                                }
                        }
@@ -144,7 +148,6 @@ establishNewPreferences()
                                CFRelease(keys);
                        }
                }
-
                /* Set the new model */
                SCPreferencesSetValue(prefs, MODEL, new_model);
        }
@@ -299,6 +302,9 @@ watchQuietEnable()
        return;
 }
 
+
+
+
 static void
 watchQuietCallback(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info)
 {
index 6b407f5d515c5300a8cca9f4ee112382746dc679..e2077df3fcdbf2221045f38015cea8b97d3c2f7b 100644 (file)
        <key>CFBundlePackageType</key>
        <string>BNDL</string>
        <key>CFBundleShortVersionString</key>
-       <string>1.12.2</string>
+       <string>1.13</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>1.12.2</string>
+       <string>1.13</string>
 </dict>
 </plist>
diff --git a/Plugins/SimulatorSupport/Info.plist b/Plugins/SimulatorSupport/Info.plist
new file mode 100644 (file)
index 0000000..72ccafd
--- /dev/null
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>Builtin</key>
+       <true/>
+       <key>CFBundleDevelopmentRegion</key>
+       <string>English</string>
+       <key>CFBundleExecutable</key>
+       <string>SimulatorSupport</string>
+       <key>CFBundleIdentifier</key>
+       <string>com.apple.SystemConfiguration.SimulatorSupport</string>
+       <key>CFBundleInfoDictionaryVersion</key>
+       <string>6.0</string>
+       <key>CFBundleName</key>
+       <string>com.apple.SystemConfiguration.SimulatorSupport</string>
+       <key>CFBundlePackageType</key>
+       <string>BNDL</string>
+       <key>CFBundleShortVersionString</key>
+       <string>1.13</string>
+       <key>CFBundleSignature</key>
+       <string>????</string>
+       <key>CFBundleVersion</key>
+       <string>1.13</string>
+</dict>
+</plist>
diff --git a/Plugins/SimulatorSupport/simulator_support.c b/Plugins/SimulatorSupport/simulator_support.c
new file mode 100644 (file)
index 0000000..529dcb8
--- /dev/null
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 2013 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@
+ */
+
+/*
+ * Modification History
+ *
+ * March 15, 2013              Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCPrivate.h>
+#include <SystemConfiguration/SCValidation.h>
+
+#include <dns_sd.h>
+#ifndef        kDNSServiceCompMulticastDNS
+#define        kDNSServiceCompMulticastDNS     "MulticastDNS"
+#endif
+#ifndef        kDNSServiceCompPrivateDNS
+#define        kDNSServiceCompPrivateDNS       "PrivateDNS"
+#endif
+
+#include "cache.h"
+
+
+static Boolean                 _verbose        = FALSE;
+static CFMutableArrayRef       mirror_keys     = NULL;
+static CFMutableArrayRef       mirror_patterns = NULL;
+static SCDynamicStoreRef       store_host      = NULL;
+static SCDynamicStoreRef       store_sim       = NULL;
+
+
+#pragma mark -
+#pragma mark iOS Simulator Support
+
+
+static void
+mirror(SCDynamicStoreRef store, CFArrayRef changes, void *info)
+{
+       CFDictionaryRef content_host;
+       CFDictionaryRef content_sim;
+       CFIndex         i;
+       CFIndex         n;
+
+       n = CFArrayGetCount(changes);
+       if (n == 0) {
+               // if no changes
+               return;
+       }
+
+       // capture "host" content
+       if (info == NULL) {
+               content_host = SCDynamicStoreCopyMultiple(store_host, changes, NULL);
+       } else {
+               content_host = (CFDictionaryRef)info;
+       }
+
+       // capture [current] "sim" content
+       content_sim = SCDynamicStoreCopyMultiple(store_sim, changes, NULL);
+
+       // update
+       cache_open();
+       for (i = 0; i < n; i++) {
+               CFStringRef             key;
+               CFPropertyListRef       val;
+
+               key = CFArrayGetValueAtIndex(changes, i);
+               val = (content_host != NULL) ? CFDictionaryGetValue(content_host, key) : NULL;
+               if (val != NULL) {
+                       // if "host" content changed
+                       cache_SCDynamicStoreSetValue(store_sim, key, val);
+               } else {
+                       // if no "host" content
+                       val = (content_sim != NULL) ? CFDictionaryGetValue(content_sim, key) : NULL;
+                       if (val != NULL) {
+                               // if we need to remove the "sim" content
+                               cache_SCDynamicStoreRemoveValue(store_sim, key);
+                       } else {
+                               // if no "sim" content to remove, just notify
+                               cache_SCDynamicStoreNotifyValue(store_sim, key);
+                       }
+               }
+       }
+       cache_write(store_sim);
+       cache_close();
+
+       // cleanup
+       if ((info == NULL) && (content_host != NULL)) {
+               CFRelease(content_host);
+       }
+       if (content_sim != NULL) {
+               CFRelease(content_sim);
+       }
+
+       return;
+}
+
+
+static void
+mirror_setup()
+{
+       CFStringRef     key;
+       CFStringRef     pattern;
+
+       mirror_keys     = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+       mirror_patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+       // Plugin:InterfaceNamer
+       key = SCDynamicStoreKeyCreate(NULL,
+                                     CFSTR("%@" "InterfaceNamer"),
+                                     kSCDynamicStoreDomainPlugin);
+       CFArrayAppendValue(mirror_keys, key);
+       CFRelease(key);
+
+       // Setup:/System
+//     key = SCDynamicStoreKeyCreateComputerName(NULL);
+//     CFArrayAppendValue(mirror_keys, key);
+//     CFRelease(key);
+
+       // Setup:/Network
+//     key = SCDynamicStoreKeyCreateHostNames(NULL);
+//     CFArrayAppendValue(mirror_keys, key);
+//     CFRelease(key);
+
+       // Setup:/Network/Global/.*
+       pattern = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+                                                            kSCDynamicStoreDomainSetup,
+                                                            kSCCompAnyRegex);
+       CFArrayAppendValue(mirror_patterns, pattern);
+       CFRelease(pattern);
+
+       // Setup:/Network/Service/.*
+       // State:/Network/Service/.*
+       pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+                                                             kSCCompAnyRegex,
+                                                             CFSTR(".*"),
+                                                             NULL);
+       CFArrayAppendValue(mirror_patterns, pattern);
+       CFRelease(pattern);
+
+       // Setup:/Network/Interface/.*
+       // State:/Network/Interface/.*
+       pattern = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+                                                               kSCCompAnyRegex,
+                                                               CFSTR(".*"),
+                                                               NULL);
+       CFArrayAppendValue(mirror_patterns, pattern);
+       CFRelease(pattern);
+
+       // State:/Network/MulticastDNS
+       key = SCDynamicStoreKeyCreate(NULL, CFSTR("%@/%@/%@"),
+                                     kSCDynamicStoreDomainState,
+                                     kSCCompNetwork,
+                                     CFSTR(kDNSServiceCompMulticastDNS));
+       CFArrayAppendValue(mirror_keys, key);
+       CFRelease(key);
+
+       // State:/Network/PrivateDNS
+       key = SCDynamicStoreKeyCreate(NULL, CFSTR("%@/%@/%@"),
+                                     kSCDynamicStoreDomainState,
+                                     kSCCompNetwork,
+                                     CFSTR(kDNSServiceCompPrivateDNS));
+       CFArrayAppendValue(mirror_keys, key);
+       CFRelease(key);
+
+       return;
+}
+
+
+#define        N_QUICK 64
+
+
+__private_extern__
+void
+prime_SimulatorSupport()
+{
+       CFDictionaryRef content_host;
+       CFIndex         n;
+
+       SCLog(_verbose, LOG_DEBUG, CFSTR("prime() called"));
+
+       // copy current content from base OS store to _Sim store
+       content_host = SCDynamicStoreCopyMultiple(store_host, mirror_keys, mirror_patterns);
+       CFRelease(mirror_keys);
+       mirror_keys = NULL;
+       CFRelease(mirror_patterns);
+       mirror_patterns = NULL;
+
+       if (content_host == NULL) {
+               return;
+       }
+
+       n = CFDictionaryGetCount(content_host);
+       if (n > 0) {
+               CFArrayRef      changes;
+               const void *    keys_host_q[N_QUICK];
+               const void **   keys_host       = keys_host_q;
+
+               if (n > (CFIndex)(sizeof(keys_host_q) / sizeof(CFStringRef))) {
+                       keys_host = CFAllocatorAllocate(NULL, n * sizeof(CFStringRef), 0);
+               }
+
+               CFDictionaryGetKeysAndValues(content_host, keys_host, NULL);
+
+               changes = CFArrayCreate(NULL, keys_host, n, &kCFTypeArrayCallBacks);
+               mirror(store_host, changes, (void *)content_host);
+               CFRelease(changes);
+
+               if (keys_host != keys_host_q) {
+                       CFAllocatorDeallocate(NULL, keys_host);
+               }
+       }
+
+       CFRelease(content_host);
+       return;
+}
+
+
+__private_extern__
+void
+load_SimulatorSupport(CFBundleRef bundle, Boolean bundleVerbose)
+{
+       Boolean                 ok;
+       CFMutableDictionaryRef  options;
+       CFRunLoopSourceRef      rls;
+
+       if (bundleVerbose) {
+               _verbose = TRUE;
+       }
+
+       SCLog(_verbose, LOG_DEBUG, CFSTR("load() called"));
+       SCLog(_verbose, LOG_DEBUG, CFSTR("  bundle ID = %@"), CFBundleGetIdentifier(bundle));
+
+       // setup
+       mirror_setup();
+
+       // setup SCDynamicStore mirroring (from "host")
+       options = CFDictionaryCreateMutable(NULL,
+                                           0,
+                                           &kCFTypeDictionaryKeyCallBacks,
+                                           &kCFTypeDictionaryValueCallBacks);
+       CFDictionarySetValue(options, kSCDynamicStoreUseHostServer, kCFBooleanTrue);
+       store_host = SCDynamicStoreCreateWithOptions(NULL,
+                                                    CFSTR("SimulatorSupport(host)"),
+                                                    options,
+                                                    mirror,
+                                                    NULL);
+       CFRelease(options);
+       assert(store_host != NULL);
+
+       ok = SCDynamicStoreSetNotificationKeys(store_host, mirror_keys, mirror_patterns);
+       assert(ok);
+
+       rls = SCDynamicStoreCreateRunLoopSource(NULL, store_host, 0);
+       assert(rls != NULL);
+
+       CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
+       CFRelease(rls);
+
+       // setup SCDynamicStore mirroring (to "iOS Simulator")
+       store_sim = SCDynamicStoreCreate(NULL,
+                                        CFSTR("SimulatorSupport(sim)"),
+                                        NULL,
+                                        NULL);
+
+       return;
+}
+
+
+#ifdef MAIN
+
+
+#pragma mark -
+#pragma mark Standalone test code
+
+
+int
+main(int argc, char **argv)
+{
+       _sc_log     = FALSE;
+       _sc_verbose = (argc > 1) ? TRUE : FALSE;
+
+       load_SimulatorSupport(CFBundleGetMainBundle(), (argc > 1) ? TRUE : FALSE);
+       prime_SimulatorSupport();
+       CFRunLoopRun();
+       // not reached
+       exit(0);
+       return 0;
+}
+#endif
diff --git a/Plugins/common/IPMonitorControlPrefs.c b/Plugins/common/IPMonitorControlPrefs.c
new file mode 100644 (file)
index 0000000..c82153e
--- /dev/null
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 2013 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@
+ */
+
+/*
+ * IPMonitorControlPrefs.c
+ * - definitions for accessing IPMonitor control preferences
+ */
+
+/*
+ * Modification History
+ *
+ * January 14, 2013    Dieter Siegmund (dieter@apple)
+ * - created
+ */
+
+#include <SystemConfiguration/SCPreferences.h>
+#include <SystemConfiguration/SCPrivate.h>
+#include <SystemConfiguration/scprefs_observer.h>
+#include <TargetConditionals.h>
+#include "IPMonitorControlPrefs.h"
+
+/*
+ * kIPMonitorControlPrefsID
+ * - identifies the IPMonitor preferences file that contains 'Verbose'
+ */
+#define kIPMonitorControlPrefsIDStr    "com.apple.IPMonitor.control.plist"
+#define kIPMonitorControlPrefsID       CFSTR(kIPMonitorControlPrefsIDStr)
+
+/*
+ * kVerbose
+ * - indicates whether IPMonitor is verbose or not
+ */
+#define kVerbose                       CFSTR("Verbose")
+
+static SCPreferencesRef                        S_prefs;
+static IPMonitorControlPrefsCallBack   S_callback;
+
+static SCPreferencesRef
+IPMonitorControlPrefsGet(void)
+{
+    if (S_prefs == NULL) {
+       IPMonitorControlPrefsInit(NULL, NULL);
+    }
+    return (S_prefs);
+}
+
+static void
+prefs_changed(__unused void * arg)
+{
+    /* get the current value */
+    if (S_callback != NULL) {
+       (*S_callback)(S_prefs);
+    }
+    return;
+}
+
+#if    TARGET_OS_IPHONE
+/*
+ * kIPMonitorControlManangedPrefsID
+ * - identifies the location of the managed preferences file
+ */
+#define kManagedPrefsDirStr            "/Library/Managed Preferences/mobile/"
+#define kIPMonitorControlManagedPrefsID        CFSTR(kManagedPrefsDirStr       \
+                                             kIPMonitorControlPrefsIDStr)
+static SCPreferencesRef                S_managed_prefs;
+
+static SCPreferencesRef
+IPMonitorControlManagedPrefsGet(void)
+{
+    if (S_managed_prefs == NULL) {
+       S_managed_prefs
+           = SCPreferencesCreate(NULL, CFSTR("IPMonitorControlPrefs"),
+                                 kIPMonitorControlManagedPrefsID);
+    }
+    return (S_managed_prefs);
+}
+
+static void
+enable_prefs_observer(CFRunLoopRef runloop)
+{
+    CFRunLoopSourceContext     context;
+    dispatch_block_t           handler;
+    dispatch_queue_t           queue;
+    CFRunLoopSourceRef         source;
+
+    bzero(&context, sizeof(context));
+    context.perform = prefs_changed;
+    source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
+    CFRunLoopAddSource(runloop, source, kCFRunLoopCommonModes);
+    queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
+    handler = ^{
+       if (source != NULL) {
+           CFRunLoopSourceSignal(source);
+           if (runloop != NULL) {
+               CFRunLoopWakeUp(runloop);
+           }
+       };
+    };
+    _scprefs_observer_watch(scprefs_observer_type_global,
+                           kIPMonitorControlPrefsIDStr,
+                           queue, handler);
+    return;
+}
+
+#else  /* TARGET_OS_IPHONE */
+
+static void
+enable_prefs_observer(CFRunLoopRef runloop)
+{
+    return;
+}
+
+#endif /* TARGET_OS_IPHONE */
+
+static void
+IPMonitorControlPrefsChanged(SCPreferencesRef prefs,
+                            SCPreferencesNotification type,
+                            void * info)
+{
+    prefs_changed(NULL);
+    return;
+}
+
+__private_extern__ SCPreferencesRef
+IPMonitorControlPrefsInit(CFRunLoopRef runloop,
+                         IPMonitorControlPrefsCallBack callback)
+{
+    S_prefs = SCPreferencesCreate(NULL, CFSTR("IPMonitorControlPrefs"),
+                                 kIPMonitorControlPrefsID);
+    if (runloop != NULL && callback != NULL) {
+       S_callback = callback;
+       SCPreferencesSetCallback(S_prefs, IPMonitorControlPrefsChanged, NULL);
+       SCPreferencesScheduleWithRunLoop(S_prefs, runloop,
+                                        kCFRunLoopCommonModes);
+       enable_prefs_observer(runloop);
+    }
+    return (S_prefs);
+}
+
+static Boolean
+IPMonitorControlPrefsSave(void)
+{
+    Boolean            saved = FALSE;
+
+    if (S_prefs != NULL) {
+       saved = SCPreferencesCommitChanges(S_prefs);
+       SCPreferencesSynchronize(S_prefs);
+    }
+    return (saved);
+}
+
+static CFBooleanRef
+prefs_get_boolean(CFStringRef key)
+{
+    CFBooleanRef       b = NULL;
+
+#if    TARGET_OS_IPHONE
+    b = SCPreferencesGetValue(IPMonitorControlManagedPrefsGet(), key);
+    b = isA_CFBoolean(b);
+#endif /* TARGET_OS_IPHONE */
+    if (b == NULL) {
+       b = SCPreferencesGetValue(IPMonitorControlPrefsGet(), key);
+       b = isA_CFBoolean(b);
+    }
+    return (b);
+}
+
+static void
+prefs_set_boolean(CFStringRef key, CFBooleanRef b)
+{
+    SCPreferencesRef   prefs = IPMonitorControlPrefsGet();
+
+    if (prefs != NULL) {
+       if (isA_CFBoolean(b) == NULL) {
+           SCPreferencesRemoveValue(prefs, key);
+       }
+       else {
+           SCPreferencesSetValue(prefs, key, b);
+       }
+    }
+    return;
+}
+
+static void
+IPMonitorControlPrefsRefresh(void)
+{
+    if (S_prefs != NULL) {
+       SCPreferencesSynchronize(S_prefs);
+    }
+#if    TARGET_OS_IPHONE
+    if (S_managed_prefs != NULL) {
+       SCPreferencesSynchronize(S_managed_prefs);
+    }
+#endif /* TARGET_OS_IPHONE */
+    return;
+}
+
+/**
+ ** Get
+ **/
+__private_extern__ Boolean
+IPMonitorControlPrefsIsVerbose(void)
+{
+    CFBooleanRef       b;
+    Boolean            verbose = FALSE;
+
+    b = prefs_get_boolean(kVerbose);
+    if (b != NULL) {
+       verbose = CFBooleanGetValue(b);
+    }
+    /* flush the backing store */
+    IPMonitorControlPrefsRefresh();
+    return (verbose);
+}
+
+/**
+ ** Set
+ **/
+__private_extern__ Boolean
+IPMonitorControlPrefsSetVerbose(Boolean verbose)
+{
+    if (verbose == FALSE) {
+       prefs_set_boolean(kVerbose, NULL);
+    }
+    else {
+       prefs_set_boolean(kVerbose, kCFBooleanTrue);
+    }
+    return (IPMonitorControlPrefsSave());
+}
+
+#ifdef TEST_IPMONITORCONTROLPREFS
+int
+main(int argc, char * argv[])
+{
+    Boolean    need_usage = FALSE;
+    Boolean    success = FALSE;
+
+    if (argc < 2) {
+       need_usage = TRUE;
+    }
+    else if (strcasecmp(argv[1], "on") == 0) {
+       success = IPMonitorControlPrefsSetVerbose(TRUE);
+    }
+    else if (strcasecmp(argv[1], "off") == 0) {
+       success = IPMonitorControlPrefsSetVerbose(FALSE);
+    }
+    else {
+       need_usage = TRUE;
+    }
+    if (need_usage) {
+       fprintf(stderr, "usage: %s ( on | off )\n", argv[0]);
+       exit(1);
+    }
+    if (success == FALSE) {
+       fprintf(stderr, "failed to save prefs\n");
+       exit(2);
+    }
+    exit(0);
+    return (0);
+}
+
+#endif /* TEST_IPMONITORCONTROLPREFS */
diff --git a/Plugins/common/IPMonitorControlPrefs.h b/Plugins/common/IPMonitorControlPrefs.h
new file mode 100644 (file)
index 0000000..e34d378
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2013 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@
+ */
+
+#ifndef _EAP8021X_EAPOLCONTROLPREFS_H
+#define _EAP8021X_EAPOLCONTROLPREFS_H
+
+/*
+ * IPMonitorControlPrefs.h
+ * - definitions for accessing IPMonitor control preferences and being notified
+ *   when they change
+ */
+
+/*
+ * Modification History
+ *
+ * January 14, 2013    Dieter Siegmund (dieter@apple)
+ * - created
+ */
+#include <CoreFoundation/CFRunLoop.h>
+#include <SystemConfiguration/SCPreferences.h>
+
+typedef void (*IPMonitorControlPrefsCallBack)(SCPreferencesRef prefs);
+
+SCPreferencesRef
+IPMonitorControlPrefsInit(CFRunLoopRef runloop,
+                         IPMonitorControlPrefsCallBack callback);
+
+Boolean
+IPMonitorControlPrefsIsVerbose(void);
+
+Boolean
+IPMonitorControlPrefsSetVerbose(Boolean verbose);
+
+#endif /* _COMMON_IPMONITORCONTROLPREFS_H */
index 22482f249427be2fa4a95cee425a8ebf5b4b535f..e930da3edbcc259cfd7c95d7e0aef850097e09f0 100644 (file)
        <key>CFBundlePackageType</key>
        <string>BNDL</string>
        <key>CFBundleShortVersionString</key>
-       <string>1.12.2</string>
+       <string>1.13</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>1.12.2</string>
+       <string>1.13</string>
        <key>CFPlugInDynamicRegistration</key>
        <string>NO</string>
        <key>CFPlugInFactories</key>
index 27d67de5faaff14f8368af80b64d632384619d67..7f34e34127ad962fce1d0d311362ed1a319e19a6 100644 (file)
@@ -63,7 +63,7 @@
  *
  *   Note: automatic configuration may not be possible if the logged in user
  *         is NOT "root" (eUID==0) or if the authorization right that governs
- *         SCHelper write operations (kSCPreferencesWriteAuthorizationRight)
+ *         SCHelper write operations (kSCPreferencesAuthorizationRight_write)
  *         is not currently available.
  *
  * An [older] "User Intervention" key is also supported.  That CFBoolean
@@ -145,7 +145,7 @@ hasAuthorization(MyType *myInstance)
                AuthorizationRights     rights;
                OSStatus                status;
 
-               items[0].name        = kSCPreferencesWriteAuthorizationRight;
+               items[0].name        = kSCPreferencesAuthorizationRight_write;
                items[0].value       = NULL;
                items[0].valueLength = 0;
                items[0].flags       = 0;
@@ -722,7 +722,7 @@ watcher_add_lan(MyType *myInstance)
                           myInstance->monitorRls,
                           kCFRunLoopDefaultMode);
 
-       // check if we already have the "admin" (kSCPreferencesWriteAuthorizationRight)
+       // check if we already have the "admin" (kSCPreferencesAuthorizationRight_write)
        // right.  If so, we can automatically configure (without user intervention) any
        // "new" network interfaces that are present at login (e.g. a USB ethernet
        // dongle that was plugged in before login).
@@ -1041,7 +1041,7 @@ watcher_add_serial(MyType *myInstance)
 
        if (myInstance->notifyNodes != NULL) {
                // if we have any serial nodes, check if we already have the
-               // "admin" (kSCPreferencesWriteAuthorizationRight) right.  If
+               // "admin" (kSCPreferencesAuthorizationRight_write) right.  If
                // so, we can automatically configure (without user intervention)
                // any "new" network interfaces that are present at login (e.g. a
                // USB modem that was plugged in before login).
index 4b4891084d6d00287849f263a3dea8f49cfdd3bf..d3c5960f79b59715977b0373855847fc6832cd4d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -228,135 +228,27 @@ add_configured_interface(const void *key, const void *value, void *context)
 }
 
 
-static void
-add_legacy_configuration(addContextRef myContext)
-{
-       CFArrayRef              bonds;
-       CFIndex                 i;
-       CFIndex                 n_bonds;
-       SCPreferencesRef        prefs;
-
-#define BOND_PREFERENCES_ID            CFSTR("VirtualNetworkInterfaces.plist")
-#define        BOND_PREFERENCES_BONDS          CFSTR("Bonds")
-#define        __kBondInterface_interface      CFSTR("interface")      // e.g. bond0, bond1, ...
-#define        __kBondInterface_devices        CFSTR("devices")        // e.g. en0, en1, ...
-#define __kBondInterface_options       CFSTR("options")        // e.g. UserDefinedName
-
-       prefs = SCPreferencesCreate(NULL, CFSTR("SCBondInterfaceCopyAll"), BOND_PREFERENCES_ID);
-       if (prefs == NULL) {
-               return;
-       }
-
-       bonds = SCPreferencesGetValue(prefs, BOND_PREFERENCES_BONDS);
-       if ((bonds != NULL) && !isA_CFArray(bonds)) {
-               CFRelease(prefs);       // if the prefs are confused
-               return;
-       }
-
-       n_bonds = (bonds != NULL) ? CFArrayGetCount(bonds) : 0;
-       for (i = 0; i < n_bonds; i++) {
-               SCBondInterfaceRef              bond;
-               CFDictionaryRef                 bond_dict;
-               CFStringRef                     bond_if;
-               CFDictionaryRef                 dict;
-               CFArrayRef                      interfaces;
-               SCNetworkInterfacePrivateRef    interfacePrivate;
-               CFIndex                         j;
-               CFMutableArrayRef               members         = NULL;
-               CFMutableDictionaryRef          newDict;
-               CFArrayRef                      newInterfaces;
-               CFIndex                         n_interfaces;
-               Boolean                         ok;
-               CFDictionaryRef                 options;
-               CFStringRef                     path;
-
-               bond_dict = CFArrayGetValueAtIndex(bonds, i);
-               if (!isA_CFDictionary(bond_dict)) {
-                       continue;       // if the prefs are confused
-               }
-
-               bond_if = CFDictionaryGetValue(bond_dict, __kBondInterface_interface);
-               if (!isA_CFString(bond_if)) {
-                       continue;       // if the prefs are confused
-               }
-
-               // check if this bond has already been allocated
-               path = CFStringCreateWithFormat(NULL,
-                                               NULL,
-                                               CFSTR("/%@/%@/%@"),
-                                               kSCPrefVirtualNetworkInterfaces,
-                                               kSCNetworkInterfaceTypeBond,
-                                               bond_if);
-               dict = SCPreferencesPathGetValue(myContext->prefs, path);
-               if (dict != NULL) {
-                       // if bond interface name not available
-                       CFRelease(path);
-                       continue;
-               }
-
-               // add a placeholder for the bond in the stored preferences
-               newDict = CFDictionaryCreateMutable(NULL,
-                                                   0,
-                                                   &kCFTypeDictionaryKeyCallBacks,
-                                                   &kCFTypeDictionaryValueCallBacks);
-               newInterfaces = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks);
-               CFDictionaryAddValue(newDict, kSCPropVirtualNetworkInterfacesBondInterfaces, newInterfaces);
-               CFRelease(newInterfaces);
-               ok = SCPreferencesPathSetValue(myContext->prefs, path, newDict);
-               CFRelease(newDict);
-               CFRelease(path);
-               if (!ok) {
-                       // if the bond could not be saved
-                       continue;
-               }
-
-               // create the bond interface
-               bond = (SCBondInterfaceRef)_SCBondInterfaceCreatePrivate(NULL, bond_if);
-
-               // estabish link to the stored configuration
-               interfacePrivate = (SCNetworkInterfacePrivateRef)bond;
-               interfacePrivate->prefs = CFRetain(myContext->prefs);
-
-               // add member interfaces
-               interfaces = CFDictionaryGetValue(bond_dict, __kBondInterface_devices);
-               n_interfaces = isA_CFArray(interfaces) ? CFArrayGetCount(interfaces) : 0;
-               for (j = 0; j < n_interfaces; j++) {
-                       CFStringRef     member;
 
-                       member = CFArrayGetValueAtIndex(interfaces, j);
-                       if (isA_CFString(member)) {
-                               add_interface(&members, member);
-                       }
-               }
-               if (members != NULL) {
-                       _SCBondInterfaceSetMemberInterfaces(bond, members);
-                       CFRelease(members);
-               }
+#pragma mark -
+#pragma mark SCBondInterface APIs
 
-               // set display name
-               options = CFDictionaryGetValue(bond_dict, __kBondInterface_options);
-               if (isA_CFDictionary(options)) {
-                       CFStringRef     name;
 
-                       name = CFDictionaryGetValue(options, kSCPropUserDefinedName);
-                       if (isA_CFString(name)) {
-                               SCBondInterfaceSetLocalizedDisplayName(bond, name);
-                       }
-               }
-
-               CFArrayAppendValue(myContext->bonds, bond);
-               CFRelease(bond);
-       }
+static __inline__ void
+my_CFDictionaryApplyFunction(CFDictionaryRef                   theDict,
+                            CFDictionaryApplierFunction        applier,
+                            void                               *context)
+{
+       CFAllocatorRef  myAllocator;
+       CFDictionaryRef myDict;
 
-       CFRelease(prefs);
+       myAllocator = CFGetAllocator(theDict);
+       myDict      = CFDictionaryCreateCopy(myAllocator, theDict);
+       CFDictionaryApplyFunction(myDict, applier, context);
+       CFRelease(myDict);
        return;
 }
 
 
-#pragma mark -
-#pragma mark SCBondInterface APIs
-
-
 CFArrayRef
 SCBondInterfaceCopyAll(SCPreferencesRef prefs)
 {
@@ -373,20 +265,10 @@ SCBondInterfaceCopyAll(SCPreferencesRef prefs)
                                        kSCPrefVirtualNetworkInterfaces,
                                        kSCNetworkInterfaceTypeBond);
        dict = SCPreferencesPathGetValue(prefs, path);
+       CFRelease(path);
        if (isA_CFDictionary(dict)) {
-               CFDictionaryApplyFunction(dict, add_configured_interface, &context);
-       } else {
-               // no bond configuration, upgrade from legacy configuration
-               dict = CFDictionaryCreate(NULL,
-                                         NULL, NULL, 0,
-                                         &kCFTypeDictionaryKeyCallBacks,
-                                         &kCFTypeDictionaryValueCallBacks);
-               (void) SCPreferencesPathSetValue(prefs, path, dict);
-               CFRelease(dict);
-
-               add_legacy_configuration(&context);
+               my_CFDictionaryApplyFunction(dict, add_configured_interface, &context);
        }
-       CFRelease(path);
 
        return context.bonds;
 }
@@ -563,6 +445,7 @@ _SCBondInterfaceCopyActive(void)
                // set the mode
                int_val = ibsr_p->ibsr_mode;
                mode = CFNumberCreate(NULL, kCFNumberIntType, &int_val);
+               assert(mode != NULL);
                _SCBondInterfaceSetMode(bond, mode);
                CFRelease(mode);
 
@@ -595,7 +478,9 @@ _SCBondInterfaceCopyActive(void)
 
     done :
 
-       (void) close(s);
+       if (s != -1) {
+               (void) close(s);
+       }
        freeifaddrs(ifap);
        return bonds;
 }
@@ -625,7 +510,7 @@ SCBondInterfaceCreate(SCPreferencesRef prefs)
                Boolean                         ok;
                CFStringRef                     path;
 
-               bond_if = CFStringCreateWithFormat(allocator, NULL, CFSTR("bond%d"), i);
+               bond_if = CFStringCreateWithFormat(allocator, NULL, CFSTR("bond%ld"), i);
                path    = CFStringCreateWithFormat(allocator,
                                                   NULL,
                                                   CFSTR("/%@/%@/%@"),
@@ -774,8 +659,9 @@ _SCBondInterfaceSetMemberInterfaces(SCBondInterfaceRef bond, CFArrayRef members)
                newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
                CFDictionarySetValue(newDict, kSCPropVirtualNetworkInterfacesBondInterfaces, newMembers);
                CFRelease(newMembers);
-
-               ok = SCPreferencesPathSetValue(interfacePrivate->prefs, path, newDict);
+               if (!CFEqual(dict, newDict)) {
+                       ok = SCPreferencesPathSetValue(interfacePrivate->prefs, path, newDict);
+               }
                CFRelease(newDict);
                CFRelease(path);
        }
@@ -925,7 +811,9 @@ SCBondInterfaceSetLocalizedDisplayName(SCBondInterfaceRef bond, CFStringRef newN
                } else {
                        CFDictionaryRemoveValue(newDict, kSCPropUserDefinedName);
                }
-               ok = SCPreferencesPathSetValue(interfacePrivate->prefs, path, newDict);
+               if (!CFEqual(dict, newDict)) {
+                       ok = SCPreferencesPathSetValue(interfacePrivate->prefs, path, newDict);
+               }
                CFRelease(newDict);
                CFRelease(path);
        }
@@ -987,7 +875,9 @@ SCBondInterfaceSetOptions(SCBondInterfaceRef bond, CFDictionaryRef newOptions)
                } else {
                        CFDictionaryRemoveValue(newDict, kSCPropVirtualNetworkInterfacesBondOptions);
                }
-               ok = SCPreferencesPathSetValue(interfacePrivate->prefs, path, newDict);
+               if (!CFEqual(dict, newDict)) {
+                       ok = SCPreferencesPathSetValue(interfacePrivate->prefs, path, newDict);
+               }
                CFRelease(newDict);
                CFRelease(path);
        }
@@ -1014,6 +904,8 @@ _SCBondInterfaceSetMode(SCBondInterfaceRef bond, CFNumberRef mode)
        Boolean                         needs_release           = FALSE;
        Boolean                         ok                      = TRUE;
 
+       assert(bond != NULL);
+
        if (mode == NULL) {
                int     mode_num        = IF_BOND_MODE_LACP;
 
@@ -1043,8 +935,9 @@ _SCBondInterfaceSetMode(SCBondInterfaceRef bond, CFNumberRef mode)
                }
                newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
                CFDictionarySetValue(newDict, kSCPropVirtualNetworkInterfacesBondMode, mode);
-
-               ok = SCPreferencesPathSetValue(interfacePrivate->prefs, path, newDict);
+               if (!CFEqual(dict, newDict)) {
+                       ok = SCPreferencesPathSetValue(interfacePrivate->prefs, path, newDict);
+               }
                CFRelease(newDict);
                CFRelease(path);
        }
index 3124eb15106f23d70b4602b26db8f47170d16d08..d291a3cef83db4bba23cb805a524d3fc020ddf6e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2009-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -155,7 +155,7 @@ static void
 add_configured_interface(const void *key, const void *value, void *context)
 {
        SCBridgeInterfaceRef            bridge;
-       CFStringRef                     bridge_if               = (CFStringRef)key;
+       CFStringRef                     bridge_if       = (CFStringRef)key;
        CFDictionaryRef                 bridge_info     = (CFDictionaryRef)value;
        CFDictionaryRef                 bridge_options;
        CFIndex                         i;
@@ -164,10 +164,16 @@ add_configured_interface(const void *key, const void *value, void *context)
        CFMutableArrayRef               members         = NULL;
        addContextRef                   myContext       = (addContextRef)context;
        CFStringRef                     name;
+       CFStringRef                     name_auto       = NULL;
        CFIndex                         n;
 
        // create the bridge interface
        bridge = (SCBridgeInterfaceRef)_SCBridgeInterfaceCreatePrivate(NULL, bridge_if);
+       assert(bridge != NULL);
+
+       // estabish link to the stored configuration
+       interfacePrivate = (SCNetworkInterfacePrivateRef)bridge;
+       interfacePrivate->prefs = CFRetain(myContext->prefs);
 
        // add member interfaces
        interfaces = CFDictionaryGetValue(bridge_info, kSCPropVirtualNetworkInterfacesBridgeInterfaces);
@@ -185,21 +191,24 @@ add_configured_interface(const void *key, const void *value, void *context)
                CFRelease(members);
        }
 
-       // set display name
-       name = CFDictionaryGetValue(bridge_info, kSCPropUserDefinedName);
-       if (isA_CFString(name)) {
-               SCBridgeInterfaceSetLocalizedDisplayName(bridge, name);
-       }
-
        // set options
        bridge_options = CFDictionaryGetValue(bridge_info, kSCPropVirtualNetworkInterfacesBridgeOptions);
        if (isA_CFDictionary(bridge_options)) {
                SCBridgeInterfaceSetOptions(bridge, bridge_options);
+               name_auto = CFDictionaryGetValue(bridge_options, CFSTR("__AUTO__"));
        }
 
-       // estabish link to the stored configuration
-       interfacePrivate = (SCNetworkInterfacePrivateRef)bridge;
-       interfacePrivate->prefs = CFRetain(myContext->prefs);
+       // set display name
+       name = CFDictionaryGetValue(bridge_info, kSCPropUserDefinedName);
+       if (isA_CFString(name)) {
+               SCBridgeInterfaceSetLocalizedDisplayName(bridge, name);
+       } else if (isA_CFString(name_auto)) {
+               interfacePrivate->localized_key = name_auto;
+               if (interfacePrivate->localized_arg1 != NULL) {
+                       CFRelease(interfacePrivate->localized_arg1);
+                       interfacePrivate->localized_arg1 = NULL;
+               }
+       }
 
        CFArrayAppendValue(myContext->bridges, bridge);
        CFRelease(bridge);
@@ -212,6 +221,22 @@ add_configured_interface(const void *key, const void *value, void *context)
 #pragma mark SCBridgeInterface APIs
 
 
+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;
+}
+
+
 CFArrayRef
 SCBridgeInterfaceCopyAll(SCPreferencesRef prefs)
 {
@@ -229,7 +254,7 @@ SCBridgeInterfaceCopyAll(SCPreferencesRef prefs)
                                        kSCNetworkInterfaceTypeBridge);
        dict = SCPreferencesPathGetValue(prefs, path);
        if (isA_CFDictionary(dict)) {
-               CFDictionaryApplyFunction(dict, add_configured_interface, &context);
+               my_CFDictionaryApplyFunction(dict, add_configured_interface, &context);
        }
        CFRelease(path);
 
@@ -378,6 +403,7 @@ _SCBridgeInterfaceCopyActive(void)
                struct ifbifconf                *ibc_p;
                struct if_data                  *if_data;
                CFMutableArrayRef               members         = NULL;
+               size_t                          n;
 
                if_data = (struct if_data *)ifp->ifa_data;
                if (if_data == NULL
@@ -386,6 +412,18 @@ _SCBridgeInterfaceCopyActive(void)
                        continue;
                }
 
+               // check the interface name ("bridgeNNN") and ensure that
+               // we leave all non-SC configured bridge interfaces (those
+               // with unit #'s >= 100) alone.
+               n = strlen(ifp->ifa_name);
+               if ((n > 3) &&
+                   isdigit(ifp->ifa_name[n - 1]) &&
+                   isdigit(ifp->ifa_name[n - 2]) &&
+                   isdigit(ifp->ifa_name[n - 3])) {
+                       // if not SC managed bridge interface
+                       continue;
+               }
+
                ibc_p = ifbifconf_copy(s, ifp->ifa_name);
                if (ibc_p == NULL) {
                        if (errno == EBUSY) {
@@ -436,7 +474,9 @@ _SCBridgeInterfaceCopyActive(void)
 
     done :
 
-       (void) close(s);
+       if (s != -1) {
+               (void) close(s);
+       }
        freeifaddrs(ifap);
        return bridges;
 }
@@ -466,7 +506,7 @@ SCBridgeInterfaceCreate(SCPreferencesRef prefs)
                Boolean                         ok;
                CFStringRef                     path;
 
-               bridge_if = CFStringCreateWithFormat(allocator, NULL, CFSTR("bridge%d"), i);
+               bridge_if = CFStringCreateWithFormat(allocator, NULL, CFSTR("bridge%ld"), i);
                path    = CFStringCreateWithFormat(allocator,
                                                   NULL,
                                                   CFSTR("/%@/%@/%@"),
@@ -615,8 +655,9 @@ _SCBridgeInterfaceSetMemberInterfaces(SCBridgeInterfaceRef bridge, CFArrayRef me
                newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
                CFDictionarySetValue(newDict, kSCPropVirtualNetworkInterfacesBridgeInterfaces, newMembers);
                CFRelease(newMembers);
-
-               ok = SCPreferencesPathSetValue(interfacePrivate->prefs, path, newDict);
+               if (!CFEqual(dict, newDict)) {
+                       ok = SCPreferencesPathSetValue(interfacePrivate->prefs, path, newDict);
+               }
                CFRelease(newDict);
                CFRelease(path);
        }
@@ -766,7 +807,9 @@ SCBridgeInterfaceSetLocalizedDisplayName(SCBridgeInterfaceRef bridge, CFStringRe
                } else {
                        CFDictionaryRemoveValue(newDict, kSCPropUserDefinedName);
                }
-               ok = SCPreferencesPathSetValue(interfacePrivate->prefs, path, newDict);
+               if (!CFEqual(dict, newDict)) {
+                       ok = SCPreferencesPathSetValue(interfacePrivate->prefs, path, newDict);
+               }
                CFRelease(newDict);
                CFRelease(path);
        }
@@ -828,7 +871,9 @@ SCBridgeInterfaceSetOptions(SCBridgeInterfaceRef bridge, CFDictionaryRef newOpti
                } else {
                        CFDictionaryRemoveValue(newDict, kSCPropVirtualNetworkInterfacesBridgeOptions);
                }
-               ok = SCPreferencesPathSetValue(interfacePrivate->prefs, path, newDict);
+               if (!CFEqual(dict, newDict)) {
+                       ok = SCPreferencesPathSetValue(interfacePrivate->prefs, path, newDict);
+               }
                CFRelease(newDict);
                CFRelease(path);
        }
@@ -840,7 +885,23 @@ SCBridgeInterfaceSetOptions(SCBridgeInterfaceRef bridge, CFDictionaryRef newOpti
                        interfacePrivate->bridge.options = NULL;
                }
                if (newOptions != NULL) {
+                       CFStringRef     name_auto       = NULL;
+
                        interfacePrivate->bridge.options = CFDictionaryCreateCopy(NULL, newOptions);
+
+                       // set [auto] display name from options
+                       if ((interfacePrivate->localized_name == NULL) &&
+                           CFDictionaryGetValueIfPresent(newOptions,
+                                                         CFSTR("__AUTO__"),
+                                                         (const void **)&name_auto) &&
+                           isA_CFString(name_auto)) {
+                               // set display name
+                               interfacePrivate->localized_key = name_auto;
+                               if (interfacePrivate->localized_arg1 != NULL) {
+                                       CFRelease(interfacePrivate->localized_arg1);
+                                       interfacePrivate->localized_arg1 = NULL;
+                               }
+                       }
                }
        }
 
@@ -984,10 +1045,10 @@ _SCBridgeInterfaceUpdateConfiguration(SCPreferencesRef prefs)
                                CFIndex         c_count;
 
                                c_bridge_interfaces = SCBridgeInterfaceGetMemberInterfaces(c_bridge);
-                               c_count           = (c_bridge_interfaces != NULL) ? CFArrayGetCount(c_bridge_interfaces) : 0;
+                               c_count             = (c_bridge_interfaces != NULL) ? CFArrayGetCount(c_bridge_interfaces) : 0;
 
                                a_bridge_interfaces = SCBridgeInterfaceGetMemberInterfaces(a_bridge);
-                               a_count           = (a_bridge_interfaces != NULL) ? CFArrayGetCount(a_bridge_interfaces) : 0;
+                               a_count             = (a_bridge_interfaces != NULL) ? CFArrayGetCount(a_bridge_interfaces) : 0;
 
                                for (a = 0; a < a_count; a++) {
                                        SCNetworkInterfaceRef   a_interface;
index f295bb690b12001e492343ad9823cacea8e75cdc..94577fe419e8869d33239b5c093ab22a2c198052 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2009, 2010, 2012, 2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #pragma mark CaptiveNetwork.framework APIs (exported through the SystemConfiguration.framework)
 
 
-#if    TARGET_OS_EMBEDDED
+#if    TARGET_OS_IPHONE
 const CFStringRef kCNNetworkInfoKeySSIDData    = CFSTR("SSIDDATA");
 const CFStringRef kCNNetworkInfoKeySSID        = CFSTR("SSID");
 const CFStringRef kCNNetworkInfoKeyBSSID       = CFSTR("BSSID");
-#endif // TARGET_OS_EMBEDDED
+#endif // TARGET_OS_IPHONE
 
 
 static void *
@@ -109,7 +109,7 @@ CNCopySupportedInterfaces(void)
 }
 
 
-#if    TARGET_OS_EMBEDDED
+#if    TARGET_OS_IPHONE
 CFDictionaryRef
 CNCopyCurrentNetworkInfo(CFStringRef   interfaceName)
 {
@@ -120,4 +120,4 @@ CNCopyCurrentNetworkInfo(CFStringRef        interfaceName)
        }
        return dyfunc ? dyfunc(interfaceName) : NULL;
 }
-#endif // TARGET_OS_EMBEDDED
+#endif // TARGET_OS_IPHONE
index 12fd409d2427482f4ce0e95d8303c276455ad421..316c31bc7bedeb1d2b1d0eee4a4e8a6d03287b7d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2009-2012 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -106,8 +106,6 @@ CNMarkPortalOffline (CFStringRef    interfaceName)          __OSX_AVAILABLE_STARTING(__MAC_
 CFArrayRef
 CNCopySupportedInterfaces      (void)                          __OSX_AVAILABLE_STARTING(__MAC_10_8,__IPHONE_4_1);
 
-#if    TARGET_OS_EMBEDDED
-
 /*!
  @constant kCNNetworkInfoKeySSIDData
  @discussion NetworkInfo Dictionary key for SSID in CFData format
@@ -148,8 +146,6 @@ extern const CFStringRef kCNNetworkInfoKeyBSSID                     __OSX_AVAILABLE_STARTING(__MAC
 CFDictionaryRef
 CNCopyCurrentNetworkInfo       (CFStringRef interfaceName)     __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_4_1);
 
-#endif // TARGET_OS_EMBEDDED
-
 __END_DECLS
 
 #endif /* _CAPTIVENETWORK_H */
index 2ea9adbd461f62b0138ef5fe896af55aabf9e37e..927ee05c3d43326cdda91f41184d66c6a82ec2ca 100644 (file)
Binary files a/SystemConfiguration.fproj/English.lproj/NetworkInterface.strings and b/SystemConfiguration.fproj/English.lproj/NetworkInterface.strings differ
index 87f9a94b8ba66d1bdc7fcd7089e08d42582bacf7..9f9b512bdc733ce4bd51eda264b1001aa5f7c7f2 100644 (file)
@@ -7,7 +7,7 @@
        <key>CFBundleExecutable</key>
        <string>SystemConfiguration</string>
        <key>CFBundleGetInfoString</key>
-       <string>1.12.2</string>
+       <string>1.13</string>
        <key>CFBundleIdentifier</key>
        <string>com.apple.SystemConfiguration</string>
        <key>CFBundleInfoDictionaryVersion</key>
        <key>CFBundlePackageType</key>
        <string>FMWK</string>
        <key>CFBundleShortVersionString</key>
-       <string>1.12.2</string>
+       <string>1.13</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>1.12.2</string>
+       <string>1.13</string>
 </dict>
 </plist>
index 87f9a94b8ba66d1bdc7fcd7089e08d42582bacf7..9f9b512bdc733ce4bd51eda264b1001aa5f7c7f2 100644 (file)
@@ -7,7 +7,7 @@
        <key>CFBundleExecutable</key>
        <string>SystemConfiguration</string>
        <key>CFBundleGetInfoString</key>
-       <string>1.12.2</string>
+       <string>1.13</string>
        <key>CFBundleIdentifier</key>
        <string>com.apple.SystemConfiguration</string>
        <key>CFBundleInfoDictionaryVersion</key>
        <key>CFBundlePackageType</key>
        <string>FMWK</string>
        <key>CFBundleShortVersionString</key>
-       <string>1.12.2</string>
+       <string>1.13</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>1.12.2</string>
+       <string>1.13</string>
 </dict>
 </plist>
index 85249b035d0db0fe24115dbb4ca7720315e65d57..f75743fe033a75c8102c43d412442a28dd6c835e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2007, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2002-2007, 2010, 2011, 2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -121,7 +121,15 @@ __getCapabilities(CFStringRef      interfaceName,
 
        if (ioctl(sock, SIOCGIFCAP, (caddr_t)&ifr) == -1) {
                _SCErrorSet(errno);
-               SCLog(TRUE, LOG_ERR, CFSTR("ioctl(SIOCGIFCAP) failed: %s"), strerror(errno));
+               switch (errno) {
+                       case EBUSY :
+                       case ENXIO :
+                               break;
+                       default :
+                               SCLog(TRUE, LOG_ERR,
+                                     CFSTR("ioctl(SIOCGIFCAP) failed: %s"),
+                                     strerror(errno));
+               }
                goto done;
        }
 
@@ -867,6 +875,15 @@ _SCNetworkInterfaceIsPhysicalEthernet(SCNetworkInterfaceRef interface)
 
        ifm = __copyMediaList(interfaceName);
        if (ifm == NULL) {
+               CFStringRef interfaceType;
+
+               interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
+               if (CFEqual(interfaceType, kSCNetworkInterfaceTypeEthernet) &&
+                   !_SCNetworkInterfaceIsTethered(interface) &&
+                   !_SCNetworkInterfaceIsBluetoothPAN(interface)) {
+                   // if likely physical ethernet interface
+                   return TRUE;
+               }
                return FALSE;
        }
        _SCErrorSet(kSCStatusOK);
@@ -1235,71 +1252,3 @@ SCNetworkInterfaceSetMTU(SCNetworkInterfaceRef   interface,
        if (newConfiguration != NULL) CFRelease(newConfiguration);
        return ok;
 }
-
-
-// XXXXX
-// XXXXX Remove the following SPIs as soon as we have migrated all
-// XXXXX internal users
-// XXXXX
-
-/* DEPRECATED */ Boolean
-NetworkInterfaceCopyMediaOptions(CFStringRef           interfaceName,
-                                CFDictionaryRef        *current,
-                                CFDictionaryRef        *active,
-                                CFArrayRef             *available,
-                                Boolean                filter)
-{
-       SCNetworkInterfacePrivateRef    interfacePrivate;
-       Boolean                         ok;
-
-       interfacePrivate = __SCNetworkInterfaceCreatePrivate(NULL, NULL, NULL, NULL);
-       if (interfacePrivate == NULL) {
-               return FALSE;
-       }
-       interfacePrivate->entity_device = CFRetain(interfaceName);
-       ok = SCNetworkInterfaceCopyMediaOptions((SCNetworkInterfaceRef)interfacePrivate,
-                                               current,
-                                               active,
-                                               available,
-                                               filter);
-       CFRelease(interfacePrivate);
-       return ok;
-}
-
-
-/* DEPRECATED */ CFArrayRef
-NetworkInterfaceCopyMediaSubTypes(CFArrayRef   available)
-{
-       return SCNetworkInterfaceCopyMediaSubTypes(available);
-}
-
-
-/* DEPRECATED */ CFArrayRef
-NetworkInterfaceCopyMediaSubTypeOptions(CFArrayRef     available,
-                                       CFStringRef     subType)
-{
-       return SCNetworkInterfaceCopyMediaSubTypeOptions(available, subType);
-}
-
-
-/* DEPRECATED */ Boolean
-NetworkInterfaceCopyMTU(CFStringRef    interfaceName,
-                       int             *mtu_cur,
-                       int             *mtu_min,
-                       int             *mtu_max)
-{
-       SCNetworkInterfacePrivateRef    interfacePrivate;
-       Boolean                         ok;
-
-       interfacePrivate = __SCNetworkInterfaceCreatePrivate(NULL, NULL, NULL, NULL);
-       if (interfacePrivate == NULL) {
-               return FALSE;
-       }
-       interfacePrivate->entity_device = CFRetain(interfaceName);
-       ok = SCNetworkInterfaceCopyMTU((SCNetworkInterfaceRef)interfacePrivate,
-                                      mtu_cur,
-                                      mtu_min,
-                                      mtu_max);
-       CFRelease(interfacePrivate);
-       return ok;
-}
diff --git a/SystemConfiguration.fproj/LinkConfiguration.h b/SystemConfiguration.fproj/LinkConfiguration.h
deleted file mode 100644 (file)
index 6a6c53f..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (c) 2002, 2004, 2006, 2008 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@
- */
-
-
-#ifndef _LINKCONFIGURATION_H
-#define _LINKCONFIGURATION_H
-
-#include <Availability.h>
-#include <sys/cdefs.h>
-#include <CoreFoundation/CoreFoundation.h>
-
-/*!
-       @header LinkConfiguration
-*/
-
-__BEGIN_DECLS
-
-/*!
-       @function NetworkInterfaceCopyMediaOptions
-       @discussion For the specified network interface, returns information
-               about the currently requested media options, the active media
-               options, and the media options which are available.
-       @param interface The desired network interface.
-       @param current A pointer to memory that will be filled with a CFDictionaryRef
-               representing the currently requested media options (subtype, options).
-               If NULL, the current options will not be returned.
-       @param active A pointer to memory that will be filled with a CFDictionaryRef
-               representing the active media options (subtype, options).
-               If NULL, the active options will not be returned.
-       @param available A pointer to memory that will be filled with a CFArrayRef
-               representing the possible media options (subtype, options).
-               If NULL, the available options will not be returned.
-       @param filter A boolean indicating whether the available options should be
-               filtered to exclude those options which would not normally be
-               requested by a user/admin (e.g. hw-loopback).
-       @result TRUE if requested information has been returned.
-
- */
-Boolean
-NetworkInterfaceCopyMediaOptions(
-                                CFStringRef            interface,
-                                CFDictionaryRef        *current,
-                                CFDictionaryRef        *active,
-                                CFArrayRef             *available,
-                                Boolean                filter
-                                )              __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_1,__MAC_10_5,__IPHONE_NA,__IPHONE_NA);
-
-/*!
-       @function NetworkInterfaceCopyMediaSubTypes
-       @discussion For the provided interface configuration options, return a list
-               of available media subtypes.
-       @param available The available options as returned by the
-               NetworkInterfaceCopyMediaOptions function.
-       @result An array of available media subtypes CFString's (e.g. 10BaseT/UTP,
-               100baseTX, etc).  NULL if no subtypes are available.
- */
-CFArrayRef
-NetworkInterfaceCopyMediaSubTypes(
-                                 CFArrayRef            available
-                                 )             __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_1,__MAC_10_5,__IPHONE_NA,__IPHONE_NA);
-
-/*!
-       @function NetworkInterfaceCopyMediaSubTypeOptions
-       @discussion For the provided interface configuration options and specific
-               subtype, return a list of available media options.
-       @param available The available options as returned by the
-               NetworkInterfaceCopyMediaOptions function.
-       @param subType The subtype
-       @result An array of available media options.  Each of the available options
-               is returned as an array of CFString's (e.g. <half-duplex>,
-               <full-duplex,flow-control>).  NULL if no options are available.
- */
-CFArrayRef
-NetworkInterfaceCopyMediaSubTypeOptions(
-                                       CFArrayRef              available,
-                                       CFStringRef             subType
-                                       )       __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_1,__MAC_10_5,__IPHONE_NA,__IPHONE_NA);
-
-/*!
-       @function NetworkInterfaceCopyMTU
-       @discussion
-       @param interface The desired network interface.
-       @param mtu_cur A pointer to memory that will be filled with the current
-               MTU setting for the interface.
-       @param mtu_min A pointer to memory that will be filled with the minimum
-               MTU setting for the interface.  If negative, the minimum setting
-               could not be determined.
-       @param mtu_max A pointer to memory that will be filled with the maximum
-               MTU setting for the interface.  If negative, the maximum setting
-               could not be determined.
-       @result TRUE if requested information has been returned.
-
- */
-Boolean
-NetworkInterfaceCopyMTU(
-                       CFStringRef     interface,
-                       int             *mtu_cur,
-                       int             *mtu_min,
-                       int             *mtu_max
-                       )                       __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_1,__MAC_10_5,__IPHONE_NA,__IPHONE_NA);
-
-
-__END_DECLS
-
-#endif /* _LINKCONFIGURATION_H */
-
index 43a21011d85dc399079ca73acc8f30bac68d5909..d6b87108e95177bc3f784a197132cea78f769d9f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2008, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2008, 2010-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -34,6 +34,8 @@
 #include <mach/mach.h>
 #include <mach/mach_error.h>
 #include <servers/bootstrap.h>
+#include <asl_msg.h>
+#include <asl_core.h>
 #include <pthread.h>
 #include <sys/time.h>
 
@@ -48,8 +50,8 @@
 int    _sc_debug       = FALSE;        /* non-zero if debugging enabled */
 int    _sc_verbose     = FALSE;        /* non-zero if verbose logging enabled */
 int    _sc_log         = TRUE;         /* 0 if SC messages should be written to stdout/stderr,
-                                          1 if SC messages should be logged w/asl(3),
-                                          2 if SC messages should be written to stdout/stderr AND logged */
+                                        1 if SC messages should be logged w/asl(3),
+                                        2 if SC messages should be written to stdout/stderr AND logged */
 
 
 #pragma mark -
@@ -87,7 +89,6 @@ __SCThreadSpecificDataRef
 __SCGetThreadSpecificData()
 {
        __SCThreadSpecificDataRef       tsd;
-
        pthread_once(&tsKeyInitialized, __SCThreadSpecificKeyInitialize);
 
        tsd = pthread_getspecific(tsDataKey);
@@ -107,6 +108,10 @@ __SCGetThreadSpecificData()
 #pragma mark Logging
 
 
+#define kASLModule             "ASLModule"
+#define kASLOption             "ASLOption"
+#define kLoggerID              "LoggerID"
+
 #define        ENABLE_SC_FORMATTING
 #ifdef ENABLE_SC_FORMATTING
 // from <CoreFoundation/ForFoundationOnly.h>
@@ -178,26 +183,26 @@ _SCCopyDescription(CFTypeRef cf, CFDictionaryRef formatOptions)
                tZone = CFTimeZoneCopySystem();
                gDate = CFAbsoluteTimeGetGregorianDate(CFDateGetAbsoluteTime(cf), tZone);
                str   = CFStringCreateWithFormat(NULL,
-                                               formatOptions,
-                                               CFSTR("%@%02d/%02d/%04d %02d:%02d:%02.0f %@"),
-                                               prefix1,
-                                               gDate.month,
-                                               gDate.day,
-                                               gDate.year,
-                                               gDate.hour,
-                                               gDate.minute,
-                                               gDate.second,
-                                               CFTimeZoneGetName(tZone));
+                                                formatOptions,
+                                                CFSTR("%@%02d/%02d/%04d %02d:%02d:%02.0f %@"),
+                                                prefix1,
+                                                gDate.month,
+                                                gDate.day,
+                                                (int)gDate.year,
+                                                gDate.hour,
+                                                gDate.minute,
+                                                gDate.second,
+                                                CFTimeZoneGetName(tZone));
                CFRelease(tZone);
                return str;
        }
 
-       if (!formatOptions ||
+       if ((formatOptions == NULL) ||
            !CFDictionaryGetValueIfPresent(formatOptions, CFSTR("PREFIX2"), (const void **)&prefix2)) {
                prefix2 = prefix1;
        }
 
-       if (formatOptions) {
+       if (formatOptions != NULL) {
                nFormatOptions = CFDictionaryCreateMutableCopy(NULL, 0, formatOptions);
        } else {
                nFormatOptions = CFDictionaryCreateMutable(NULL,
@@ -205,6 +210,7 @@ _SCCopyDescription(CFTypeRef cf, CFDictionaryRef formatOptions)
                                                           &kCFTypeDictionaryKeyCallBacks,
                                                           &kCFTypeDictionaryValueCallBacks);
        }
+       assert(nFormatOptions != NULL);
 
 #define        N_QUICK 32
 
@@ -229,7 +235,7 @@ _SCCopyDescription(CFTypeRef cf, CFDictionaryRef formatOptions)
                                CFStringRef             nStr;
                                CFStringRef             vStr;
 
-                               nStr = CFStringCreateWithFormat(NULL, NULL, CFSTR("%u"), i);
+                               nStr = CFStringCreateWithFormat(NULL, NULL, CFSTR("%ld"), i);
 
                                nPrefix1 = CFStringCreateMutable(NULL, 0);
                                CFStringAppendFormat(nPrefix1,
@@ -355,7 +361,6 @@ _SCCopyDescription(CFTypeRef cf, CFDictionaryRef formatOptions)
 
 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
 
-
 static void
 __SCLog(aslclient asl, aslmsg msg, int level, CFStringRef formatString, va_list formatArguments)
 {
@@ -606,6 +611,432 @@ SCTrace(Boolean condition, FILE *stream, CFStringRef formatString, ...)
 }
 
 
+#pragma mark -
+#pragma mark ASL Functions
+
+
+#if    ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 60000))
+
+
+extern kern_return_t _asl_server_query(mach_port_t server,
+                                      caddr_t request,
+                                      mach_msg_type_number_t requestCnt,
+                                      uint64_t startid,
+                                      int count,
+                                      int flags,
+                                      caddr_t *reply,
+                                      mach_msg_type_number_t *replyCnt,
+                                      uint64_t *lastid,
+                                      int *status,
+                                      security_token_t *token);
+
+#define ASL_SERVICE_NAME "com.apple.system.logger"
+
+
+static aslresponse
+_asl_control_query(aslmsg a)
+{
+       asl_search_result_t *out;
+       char *qstr, *str, *res;
+       uint32_t len, reslen, status;
+       uint64_t cmax, qmin;
+       kern_return_t kstatus;
+       caddr_t vmstr;
+       mach_port_t server_port;
+       security_token_t sec;
+
+       bootstrap_look_up(bootstrap_port, ASL_SERVICE_NAME, &server_port);
+       if (server_port == MACH_PORT_NULL) return NULL;
+
+       len = 0;
+       qstr = asl_msg_to_string((asl_msg_t *)a, &len);
+
+       str = NULL;
+       if (qstr == NULL)
+       {
+               asprintf(&str, "1\nQ [= ASLOption control]\n");
+               len = 27;
+       }
+       else
+       {
+               asprintf(&str, "1\n%s [= ASLOption control]\n", qstr);
+               len += 26;
+               free(qstr);
+       }
+
+       if (str == NULL) return NULL;
+
+       out = NULL;
+       qmin = 0;
+       cmax = 0;
+       sec.val[0] = -1;
+       sec.val[1] = -1;
+
+       res = NULL;
+       reslen = 0;
+       status = ASL_STATUS_OK;
+
+       kstatus = vm_allocate(mach_task_self(), (vm_address_t *)&vmstr, len, TRUE);
+       if (kstatus != KERN_SUCCESS) return NULL;
+
+       memmove(vmstr, str, len);
+       free(str);
+
+       status = 0;
+       kstatus = _asl_server_query(server_port, vmstr, len, qmin, 1, 0, (caddr_t *)&res, &reslen, &cmax, (int *)&status, &sec);
+       if (kstatus != KERN_SUCCESS) return NULL;
+
+       if (res == NULL) return NULL;
+
+       out = asl_list_from_string(res);
+       vm_deallocate(mach_task_self(), (vm_address_t)res, reslen);
+
+       return out;
+}
+
+
+static CFTypeID __kSCLoggerTypeID = _kCFRuntimeNotATypeID;
+
+typedef  enum {
+       kModuleStatusEnabled,
+       kModuleStatusDisabled,
+       kModuleStatusDoesNotExist
+} ModuleStatus;
+
+struct SCLogger
+{
+       CFRuntimeBase           cf_base;
+
+       char *                  loggerID;       // LoggerID
+       SCLoggerFlags           flags;
+       aslclient               aslc;
+       aslmsg                  aslm;
+       ModuleStatus            module_status;
+       pthread_mutex_t         lock;
+};
+
+
+static void __SCLoggerDeallocate(CFTypeRef cf);
+static const CFRuntimeClass __SCLoggerClass = {
+       0,                              /* version */
+       "SCLogger",                     /* className */
+       NULL,                           /* init */
+       NULL,                           /* copy */
+       __SCLoggerDeallocate,           /* deallocate */
+       NULL,                           /* equal */
+       NULL,                           /* hash */
+       NULL,                           /* copyFormattingDesc */
+       NULL                            /* copyDebugDesc */
+};
+
+
+#define                DATETIMEBUFFERSIZE      32
+
+
+static pthread_once_t  registerLoggerOnce = PTHREAD_ONCE_INIT;
+static pthread_once_t  defaultLoggerOnce = PTHREAD_ONCE_INIT;
+
+typedef enum {
+       kLoggerASLControlEnableModule,
+       kLoggerASLControlDisableModule,
+       kLoggerASLControlLogFileCheckpoint
+} LoggerASLControl;
+
+static SCLoggerRef     defaultLogger = NULL;
+static SCLoggerRef     __SCLoggerCreate(void);
+static void            __SCLoggerDefaultLoggerInit();
+static SCLoggerRef     SCLoggerGetDefaultLogger();
+static void            SCLoggerSetLoggerID(SCLoggerRef logger, CFStringRef loggerID);
+static void            SCLoggerSendMessageToModuleOnly(SCLoggerRef logger, Boolean isPrivate);
+static void            SCLoggerSendASLControl(SCLoggerRef logger, LoggerASLControl control);
+static ModuleStatus    GetModuleStatus(const char * loggerID);
+
+static void
+__SCLoggerRegisterClass(void)
+{
+       if (__kSCLoggerTypeID == _kCFRuntimeNotATypeID) {
+               __kSCLoggerTypeID = _CFRuntimeRegisterClass(&__SCLoggerClass);
+       }
+       return;
+}
+
+static SCLoggerRef
+__SCLoggerAllocate(CFAllocatorRef allocator)
+{
+       SCLoggerRef state;
+       int size;
+
+       pthread_once(&registerLoggerOnce, __SCLoggerRegisterClass);
+
+       size = sizeof(*state) - sizeof(CFRuntimeBase);
+       state = (SCLoggerRef) _CFRuntimeCreateInstance(allocator,
+                                                      __kSCLoggerTypeID,
+                                                      size,
+                                                      NULL);
+       bzero((void*)state + sizeof(CFRuntimeBase), size);
+       return (state);
+}
+
+static void
+__SCLoggerDeallocate(CFTypeRef cf)
+{
+       SCLoggerRef logger = (SCLoggerRef)cf;
+
+       if (logger != NULL) {
+               // Rotate on close behavior
+               if (logger->module_status != kModuleStatusDoesNotExist) {
+                       SCLoggerSendASLControl(logger,
+                                              kLoggerASLControlLogFileCheckpoint);
+               }
+               if (logger->loggerID != NULL) {
+                       CFAllocatorDeallocate(NULL, logger->loggerID);
+                       logger->loggerID = NULL;
+               }
+               if (logger->aslm != NULL) {
+                       asl_free(logger->aslm);
+                       logger->aslm = NULL;
+               }
+               if (logger->aslc != NULL) {
+                       asl_close(logger->aslc);
+                       logger->aslc = NULL;
+               }
+       }
+}
+
+static SCLoggerRef
+__SCLoggerCreate(void)
+{
+       SCLoggerRef tempLogger = NULL;
+
+       tempLogger = __SCLoggerAllocate(kCFAllocatorDefault);
+       tempLogger->loggerID = NULL;
+       tempLogger->flags = kSCLoggerFlagsDefault;
+       tempLogger->aslc = asl_open(NULL, NULL, ASL_OPT_NO_DELAY);
+       tempLogger->aslm = asl_new(ASL_TYPE_MSG);
+       pthread_mutex_init(&(tempLogger->lock), NULL);
+       tempLogger->module_status = kModuleStatusDoesNotExist;
+
+       return tempLogger;
+}
+
+SCLoggerFlags
+SCLoggerGetFlags(SCLoggerRef logger)
+{
+       return logger->flags;
+}
+
+void
+SCLoggerSetFlags(SCLoggerRef logger, SCLoggerFlags flags)
+{
+       if (logger == defaultLogger) {
+               return;
+       }
+       pthread_mutex_lock(&(logger->lock));
+       if (flags != kSCLoggerFlagsNone) {
+               logger->module_status = GetModuleStatus(logger->loggerID);
+               if (logger->module_status == kModuleStatusDoesNotExist) {
+                       goto done;
+               }
+               if ((flags & kSCLoggerFlagsFile) != 0) {
+                       if ((logger->flags & kSCLoggerFlagsFile) == 0) {
+                               // Enable the module if disabled
+                               if (logger->module_status == kModuleStatusDisabled) {
+                                       SCLoggerSendASLControl(logger, kLoggerASLControlEnableModule);
+                               }
+                               // Setting ASL Filter level to debug
+                               asl_set_filter(logger->aslc, ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG));
+                               if (logger->loggerID != NULL) {
+                                       asl_set(logger->aslm, kLoggerID,
+                                               logger->loggerID);
+                               }
+                       }
+               }
+               else if ((logger->flags & kSCLoggerFlagsFile) != 0) {
+                       asl_unset(logger->aslm, kLoggerID);
+                       asl_set_filter(logger->aslc, ASL_FILTER_MASK_UPTO(ASL_LEVEL_NOTICE));
+                       SCLoggerSendMessageToModuleOnly(logger, false);
+               }
+               if ((flags & kSCLoggerFlagsDefault) != 0) {
+                       if ((logger->flags & kSCLoggerFlagsDefault) == 0) {
+                               SCLoggerSendMessageToModuleOnly(logger, false);
+                       }
+               }
+               else if ((logger->flags & kSCLoggerFlagsDefault) != 0) {
+                       SCLoggerSendMessageToModuleOnly(logger, true);
+               }
+       }
+       logger->flags = flags;
+   done:
+       pthread_mutex_unlock(&(logger->lock));
+}
+
+
+static void
+SCLoggerSetLoggerID(SCLoggerRef logger, CFStringRef loggerID)
+{
+       logger->loggerID
+               = _SC_cfstring_to_cstring(loggerID, NULL, 0,
+                                         kCFStringEncodingUTF8);
+       // Enable the module if disabled
+       logger->module_status = GetModuleStatus(logger->loggerID);
+       if (logger->module_status == kModuleStatusDisabled) {
+               SCLoggerSendASLControl(logger, kLoggerASLControlEnableModule);
+       }
+}
+
+static ModuleStatus
+GetModuleStatus(const char * loggerID)
+{
+       aslresponse response = NULL;
+       aslmsg responseMessage = NULL;
+       ModuleStatus moduleStatus = kModuleStatusDoesNotExist;
+       const char* value = NULL;
+
+       if (loggerID != NULL) {
+               response = _asl_control_query(NULL);
+               if (response == NULL) {
+                       goto done;
+               }
+               responseMessage = aslresponse_next(response);
+               if (responseMessage == NULL) {
+                       goto done;
+               }
+               value = asl_get(responseMessage, loggerID);
+               if (value == NULL) {
+                       moduleStatus = kModuleStatusDoesNotExist;
+                       goto done;
+               }
+
+               if (strcmp(value, "enabled") == 0) {
+                       moduleStatus = kModuleStatusEnabled;
+               }
+               else {
+                       moduleStatus = kModuleStatusDisabled;
+               }
+       }
+done:
+       if (response != NULL) {
+               aslresponse_free(response);
+       }
+
+       return moduleStatus;
+}
+
+static void
+SCLoggerSendMessageToModuleOnly(SCLoggerRef logger, Boolean isPrivate)
+{
+       if (isPrivate) {
+               asl_set(logger->aslm, kASLModule, logger->loggerID);
+       }
+       else {
+               if (asl_get(logger->aslm, kASLModule) != NULL) {
+                       asl_unset(logger->aslm, kASLModule);
+               }
+       }
+}
+
+static void
+SCLoggerSendASLControl(SCLoggerRef logger, LoggerASLControl control)
+{
+       SCLoggerRef defLogger = SCLoggerGetDefaultLogger();
+       pthread_mutex_lock(&(defLogger->lock));
+
+       // this next line turns the asl_log()'s that follow into control messages
+       asl_set(defLogger->aslm, kASLOption, "control");
+
+       switch (control) {
+               case kLoggerASLControlEnableModule:
+                       asl_log(defLogger->aslc, defLogger->aslm,
+                               ASL_LEVEL_NOTICE, "@ %s enable 1",
+                               logger->loggerID);
+                       break;
+               case kLoggerASLControlDisableModule:
+                       asl_log(defLogger->aslc, defLogger->aslm,
+                               ASL_LEVEL_NOTICE, "@ %s enable 0",
+                               logger->loggerID);
+                       break;
+               case kLoggerASLControlLogFileCheckpoint:
+                       asl_log(defLogger->aslc, defLogger->aslm,
+                               ASL_LEVEL_NOTICE, "@ %s checkpoint",
+                               logger->loggerID);
+                       break;
+               default:
+                       break;
+       }
+
+       // turn off control mode
+       asl_unset(defLogger->aslm, kASLOption);
+       pthread_mutex_unlock(&defLogger->lock);
+       return;
+}
+
+SCLoggerRef
+SCLoggerCreate(CFStringRef loggerID)
+{
+       SCLoggerRef logger = NULL;
+
+       logger = __SCLoggerCreate();
+       if (loggerID != NULL) {
+               SCLoggerSetLoggerID(logger, loggerID);
+       }
+       SCLoggerSetFlags(logger, kSCLoggerFlagsDefault);
+       return logger;
+}
+
+static void
+__SCLoggerDefaultLoggerInit()
+{
+       if (defaultLogger == NULL) {
+               defaultLogger = __SCLoggerCreate();
+               defaultLogger->flags = kSCLoggerFlagsDefault;
+       }
+}
+
+static SCLoggerRef
+SCLoggerGetDefaultLogger()
+{
+       pthread_once(&defaultLoggerOnce, __SCLoggerDefaultLoggerInit);
+       return defaultLogger;
+}
+
+void
+SCLoggerVLog(SCLoggerRef logger, int loglevel, CFStringRef formatString,
+            va_list args)
+{
+       aslclient       aslc;
+       aslmsg          aslm;
+
+       if (logger == NULL
+           || logger->module_status == kModuleStatusDoesNotExist) {
+               logger = SCLoggerGetDefaultLogger();
+       }
+       pthread_mutex_lock(&(logger->lock));
+       if (logger->flags == kSCLoggerFlagsNone) {
+               pthread_mutex_unlock(&(logger->lock));
+               return;
+       }
+       aslc = logger->aslc;
+       aslm = logger->aslm;
+       __SCLog(aslc, aslm, loglevel, formatString, args);
+       pthread_mutex_unlock(&(logger->lock));
+       return;
+}
+
+void
+SCLoggerLog(SCLoggerRef logger, int loglevel, CFStringRef formatString, ...)
+{
+       va_list args;
+
+       va_start(args, formatString);
+       SCLoggerVLog(logger, loglevel, formatString, args);
+       va_end(args);
+
+       return;
+}
+
+#endif // ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 60000))
+
+
 #pragma mark -
 #pragma mark SC error handling / logging
 
@@ -618,6 +1049,7 @@ static const struct sc_errmsg {
        char    *message;
 } sc_errmsgs[] = {
        { kSCStatusAccessError,         "Permission denied" },
+       { kSCStatusConnectionIgnore,    "Network connection information not available at this time" },
        { kSCStatusConnectionNoService, "Network service for connection not available" },
        { kSCStatusFailed,              "Failed!" },
        { kSCStatusInvalidArgument,     "Invalid argument" },
@@ -639,7 +1071,6 @@ static const struct sc_errmsg {
 };
 #define nSC_ERRMSGS (sizeof(sc_errmsgs)/sizeof(struct sc_errmsg))
 
-
 void
 _SCErrorSet(int error)
 {
@@ -689,7 +1120,7 @@ SCCopyLastError(void)
 
        domain = kCFErrorDomainMach;
 
-    done :
+       done :
 
        error = CFErrorCreate(NULL, domain, code, userInfo);
        if (userInfo != NULL) CFRelease(userInfo);
index 2652bc421619dab71e935d6e14d46323311105c9..02e7d48911fb7f11382af001d486c667a7197e71 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2005, 2008-2012 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2005, 2008-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -88,16 +88,6 @@ rlsCallback(CFMachPortRef port, void *msg, CFIndex size, void *info)
 }
 
 
-static void
-portInvalidate(CFMachPortRef port, void *info) {
-       mach_port_t     mp      = CFMachPortGetPort(port);
-
-       __MACH_PORT_DEBUG(TRUE, "*** portInvalidate", mp);
-       /* remove our receive right  */
-       (void)mach_port_mod_refs(mach_task_self(), mp, MACH_PORT_RIGHT_RECEIVE, -1);
-}
-
-
 static void
 rlsSchedule(void *info, CFRunLoopRef rl, CFStringRef mode)
 {
@@ -200,10 +190,9 @@ rlsSchedule(void *info, CFRunLoopRef rl, CFStringRef mode)
 
                __MACH_PORT_DEBUG(TRUE, "*** rlsSchedule (after notifyviaport)", port);
                storePrivate->rlsNotifyPort = _SC_CFMachPortCreateWithPort("SCDynamicStore",
-                                                                    port,
-                                                                    rlsCallback,
-                                                                    &context);
-               CFMachPortSetInvalidationCallBack(storePrivate->rlsNotifyPort, portInvalidate);
+                                                                          port,
+                                                                          rlsCallback,
+                                                                          &context);
                storePrivate->rlsNotifyRLS = CFMachPortCreateRunLoopSource(NULL, storePrivate->rlsNotifyPort, 0);
 
                storePrivate->rlList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
@@ -278,13 +267,20 @@ rlsCancel(void *info, CFRunLoopRef rl, CFStringRef mode)
                }
 
                if (storePrivate->rlsNotifyPort != NULL) {
-                       /* invalidate port */
+                       mach_port_t     mp;
+
+                       mp = CFMachPortGetPort(storePrivate->rlsNotifyPort);
                        __MACH_PORT_DEBUG((storePrivate->rlsNotifyPort != NULL),
-                                         "*** rlsCancel (before invalidating CFMachPort)",
-                                         CFMachPortGetPort(storePrivate->rlsNotifyPort));
+                                         "*** rlsCancel (before invalidating/releasing CFMachPort)",
+                                         mp);
+
+                       /* invalidate and release port */
                        CFMachPortInvalidate(storePrivate->rlsNotifyPort);
                        CFRelease(storePrivate->rlsNotifyPort);
                        storePrivate->rlsNotifyPort = NULL;
+
+                       /* and, finally, remove our receive right  */
+                       (void)mach_port_mod_refs(mach_task_self(), mp, MACH_PORT_RIGHT_RECEIVE, -1);
                }
 
                if (storePrivate->server != MACH_PORT_NULL) {
@@ -343,8 +339,10 @@ rlsPerform(void *info)
                context_info    = storePrivate->rlsContext.info;
                context_release = NULL;
        }
-       (*rlsFunction)(store, changedKeys, context_info);
-       if (context_release) {
+       if (rlsFunction != NULL) {
+               (*rlsFunction)(store, changedKeys, context_info);
+       }
+       if (context_release != NULL) {
                context_release(context_info);
        }
 
index c8090bb04b28a5cfc93d855df3f592656cac4c07..abe97272b3f3de1f435868857d63780ad3f6878b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2006, 2008-2012 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2006, 2008-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -73,7 +73,7 @@ __SCDynamicStoreCopyDescription(CFTypeRef cf) {
        result = CFStringCreateMutable(allocator, 0);
        CFStringAppendFormat(result, NULL, CFSTR("<SCDynamicStore %p [%p]> {"), cf, allocator);
        if (storePrivate->server != MACH_PORT_NULL) {
-               CFStringAppendFormat(result, NULL, CFSTR("server port = %p"), storePrivate->server);
+               CFStringAppendFormat(result, NULL, CFSTR("server port = 0x%x"), storePrivate->server);
        } else {
                CFStringAppendFormat(result, NULL, CFSTR("server not (no longer) available"));
        }
@@ -236,25 +236,27 @@ __SCDynamicStoreInitialize(void)
 
 
 static mach_port_t
-__SCDynamicStoreServerPort(kern_return_t *status)
+__SCDynamicStoreServerPort(SCDynamicStorePrivateRef storePrivate, kern_return_t *status)
 {
        mach_port_t     server  = MACH_PORT_NULL;
        char            *server_name;
 
        server_name = getenv("SCD_SERVER");
-       if (!server_name) {
+
+
+       if (server_name == NULL) {
                server_name = SCD_SERVER;
        }
 
-#ifdef BOOTSTRAP_PRIVILEGED_SERVER
+#if    defined(BOOTSTRAP_PRIVILEGED_SERVER) && !TARGET_IPHONE_SIMULATOR
        *status = bootstrap_look_up2(bootstrap_port,
                                     server_name,
                                     &server,
                                     0,
                                     BOOTSTRAP_PRIVILEGED_SERVER);
-#else  // BOOTSTRAP_PRIVILEGED_SERVER
+#else  // defined(BOOTSTRAP_PRIVILEGED_SERVER) && !TARGET_IPHONE_SIMULATOR
        *status = bootstrap_look_up(bootstrap_port, server_name, &server);
-#endif // BOOTSTRAP_PRIVILEGED_SERVER
+#endif // defined(BOOTSTRAP_PRIVILEGED_SERVER) && !TARGET_IPHONE_SIMULATOR
 
        switch (*status) {
                case BOOTSTRAP_SUCCESS :
@@ -363,6 +365,31 @@ __SCDynamicStoreCreatePrivate(CFAllocatorRef               allocator,
 }
 
 
+static void
+updateServerPort(SCDynamicStorePrivateRef storePrivate, mach_port_t *server, int *sc_status_p)
+{
+       pthread_mutex_lock(&_sc_lock);
+       if (_sc_server != MACH_PORT_NULL) {
+               if (*server == _sc_server) {
+                       // if the server we tried returned the error, deallocate
+                       // our send [or dead name] right
+                       (void)mach_port_deallocate(mach_task_self(), _sc_server);
+
+                       // and [re-]lookup the name to the server
+                       _sc_server = __SCDynamicStoreServerPort(storePrivate, sc_status_p);
+               } else {
+                       // another thread has refreshed the SCDynamicStore server port
+               }
+       } else {
+               _sc_server = __SCDynamicStoreServerPort(storePrivate, sc_status_p);
+       }
+       *server = _sc_server;
+       pthread_mutex_unlock(&_sc_lock);
+
+       return;
+}
+
+
 static Boolean
 __SCDynamicStoreAddSession(SCDynamicStorePrivateRef storePrivate)
 {
@@ -390,6 +417,11 @@ __SCDynamicStoreAddSession(SCDynamicStorePrivateRef storePrivate)
 
        /* open a new session with the server */
        server = _sc_server;
+
+
+       updateServerPort(storePrivate, &server, &sc_status);
+
+
        while (TRUE) {
                if (server != MACH_PORT_NULL) {
                        if (!storePrivate->serverNullSession) {
@@ -427,23 +459,8 @@ __SCDynamicStoreAddSession(SCDynamicStorePrivateRef storePrivate)
                        }
                }
 
-               pthread_mutex_lock(&_sc_lock);
-               if (_sc_server != MACH_PORT_NULL) {
-                       if (server == _sc_server) {
-                               // if the server we tried returned the error, deallocate
-                               // our send [or dead name] right
-                               (void)mach_port_deallocate(mach_task_self(), _sc_server);
 
-                               // and [re-]lookup the name to the server
-                               _sc_server = __SCDynamicStoreServerPort(&sc_status);
-                       } else {
-                               // another thread has refreshed the SCDynamicStore server port
-                       }
-               } else {
-                       _sc_server = __SCDynamicStoreServerPort(&sc_status);
-               }
-               server = _sc_server;
-               pthread_mutex_unlock(&_sc_lock);
+               updateServerPort(storePrivate, &server, &sc_status);
 
                if (server == MACH_PORT_NULL) {
                        // if SCDynamicStore server not available
@@ -495,6 +512,7 @@ __SCDynamicStoreNullSession(void)
                                                             CFSTR("NULL session"),
                                                             NULL,
                                                             NULL);
+               assert(storePrivate != NULL);
                storePrivate->server = _sc_server;
                storePrivate->serverNullSession = TRUE;
 #else
@@ -508,6 +526,7 @@ __SCDynamicStoreNullSession(void)
                                                             CFSTR("Thread local session"),
                                                             NULL,
                                                             NULL);
+               assert(storePrivate != NULL);
                /*
                 * Use MACH_PORT_NULL here to trigger the call to
                 * __SCDynamicStoreAddSession below.
@@ -732,6 +751,7 @@ __SCDynamicStoreReconnectNotifications(SCDynamicStoreRef store)
 const CFStringRef      kSCDynamicStoreUseSessionKeys   = CFSTR("UseSessionKeys");      /* CFBoolean */
 
 
+
 SCDynamicStoreRef
 SCDynamicStoreCreateWithOptions(CFAllocatorRef         allocator,
                                CFStringRef             name,
@@ -756,7 +776,10 @@ SCDynamicStoreCreateWithOptions(CFAllocatorRef             allocator,
        }
 
        // set "options"
-       storePrivate->options = (storeOptions != NULL) ? CFRetain(storeOptions) : NULL;
+
+       if (storeOptions != NULL) {
+               storePrivate->options = CFRetain(storeOptions);
+       }
 
        // establish SCDynamicStore session
        ok = __SCDynamicStoreAddSession(storePrivate);
index 8431f3c4e3620d3c7bbd6d2489e572fbbc049b57..926500f98a1a91eae3a2ba72a43348451340f52c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2002-2006, 2013 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -278,11 +278,22 @@ _SCDPluginExecCommand2(SCDPluginExecCallBack      callout,
                       void                     *setupContext
                       )
 {
-       pid_t   pid;
+       char            buf[1024];
+       pid_t           pid;
+       struct passwd   pwd;
+       struct passwd   *result = NULL;
+       char            *username = NULL;
 
        // grab the activeChildren mutex
        pthread_mutex_lock(&lock);
 
+       // cache the getpwuid_r result here to avoid spinning that can happen
+       // when calling it between fork and execv.
+       if ((getpwuid_r(uid, &pwd, buf, sizeof(buf), &result) == 0) &&
+           (result != NULL)) {
+               username = result->pw_name;
+       }
+
        // if needed, initialize
        if (childReaped == NULL) {
                _SCDPluginExecInit();
@@ -325,15 +336,8 @@ _SCDPluginExecCommand2(SCDPluginExecCallBack       callout,
                                (void) setgid(gid);
                        }
 
-                       if ((euid != uid) || (egid != gid)) {
-                               char            buf[1024];
-                               struct passwd   pwd;
-                               struct passwd   *result = NULL;
-
-                               if ((getpwuid_r(uid, &pwd, buf, sizeof(buf), &result) == 0) &&
-                                   (result != NULL)) {
-                                       initgroups(result->pw_name, gid);
-                               }
+                       if (((euid != uid) || (egid != gid)) && username) {
+                               initgroups(username, gid);
                        }
 
                        if (euid != uid) {
index 0f3e346debc02b366815683f6a43a8d93d972dd8..5610bb7d10ccf793a0cb63345cf5d075ed5e1b64 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2012 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -41,6 +41,7 @@
 #include <sys/param.h>
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <sys/ioctl.h>
 #include <net/if.h>
 #include <net/if_dl.h>
 #include <netinet/in.h>
@@ -56,9 +57,9 @@
 #include <dlfcn.h>
 
 
-#if    TARGET_OS_EMBEDDED && !TARGET_OS_EMBEDDED_OTHER && !defined(DO_NOT_INFORM)
+#if    TARGET_OS_EMBEDDED && !defined(DO_NOT_INFORM)
 #include <CoreFoundation/CFUserNotification.h>
-#endif // TARGET_OS_EMBEDDED && !TARGET_OS_EMBEDDED_OTHER && !defined(DO_NOT_INFORM)
+#endif // TARGET_OS_EMBEDDED && !defined(DO_NOT_INFORM)
 
 #define        N_QUICK 32
 
@@ -161,15 +162,6 @@ _SC_sockaddr_to_string(const struct sockaddr *address, char *buf, size_t bufLen)
                        }
                        break;
                }
-               case AF_LINK :
-                       if (addr.sdl->sdl_len < bufLen) {
-                               bufLen = addr.sdl->sdl_len;
-                       } else {
-                               bufLen = bufLen - 1;
-                       }
-
-                       bcopy(addr.sdl->sdl_data, buf, bufLen);
-                       break;
                default :
                        snprintf(buf, bufLen, "unexpected address family %d", address->sa_family);
                        break;
@@ -542,6 +534,7 @@ _SCUnserializeData(CFDataRef *data, void *dataRef, CFIndex dataLen)
 CF_RETURNS_RETAINED CFDictionaryRef
 _SCSerializeMultiple(CFDictionaryRef dict)
 {
+       CFIndex                 i;
        const void *            keys_q[N_QUICK];
        const void **           keys            = keys_q;
        CFIndex                 nElements;
@@ -553,17 +546,16 @@ _SCSerializeMultiple(CFDictionaryRef dict)
 
        nElements = CFDictionaryGetCount(dict);
        if (nElements > 0) {
-               CFIndex i;
-
                if (nElements > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) {
                        keys   = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0);
                        values = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0);
-                       pLists = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0);
+                       pLists = CFAllocatorAllocate(NULL, nElements * sizeof(CFDataRef), 0);
                }
-               bzero(pLists, nElements * sizeof(CFTypeRef));
+               bzero(pLists, nElements * sizeof(CFDataRef));
 
                CFDictionaryGetKeysAndValues(dict, keys, values);
                for (i = 0; i < nElements; i++) {
+                       pLists[i] = NULL;
                        if (!_SCSerialize((CFPropertyListRef)values[i], (CFDataRef *)&pLists[i], NULL, NULL)) {
                                goto done;
                        }
@@ -580,10 +572,8 @@ _SCSerializeMultiple(CFDictionaryRef dict)
     done :
 
        if (nElements > 0) {
-               CFIndex i;
-
                for (i = 0; i < nElements; i++) {
-                       if (pLists[i])  CFRelease(pLists[i]);
+                       if (pLists[i] != NULL)  CFRelease((CFDataRef)pLists[i]);
                }
 
                if (keys != keys_q) {
@@ -892,6 +882,7 @@ _SC_CFBundleCopyNonLocalizedString(CFBundleRef bundle, CFStringRef key, CFString
 {
        CFDataRef       data    = NULL;
        SInt32          errCode = 0;
+       Boolean         ok;
        CFURLRef        resourcesURL;
        CFStringRef     str     = NULL;
        CFURLRef        url;
@@ -921,12 +912,16 @@ _SC_CFBundleCopyNonLocalizedString(CFBundleRef bundle, CFStringRef key, CFString
                CFRelease(fileName);
                CFRelease(resourcesURL);
 
-               if (!CFURLCreateDataAndPropertiesFromResource(NULL,
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated"
+               ok = CFURLCreateDataAndPropertiesFromResource(NULL,
                                                              url,
                                                              &data,
                                                              NULL,
                                                              NULL,
-                                                             &errCode)) {
+                                                             &errCode);
+#pragma GCC diagnostic pop
+               if (!ok) {
                        /*
                         * Failed to get the data using a manually-constructed URL
                         * for the given strings table. Fall back to using
@@ -944,12 +939,16 @@ _SC_CFBundleCopyNonLocalizedString(CFBundleRef bundle, CFStringRef key, CFString
                                                             NULL,
                                                             CFSTR("English"));
                if (url != NULL) {
-                       if (!CFURLCreateDataAndPropertiesFromResource(NULL,
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated"
+                       ok = CFURLCreateDataAndPropertiesFromResource(NULL,
                                                                      url,
                                                                      &data,
                                                                      NULL,
                                                                      NULL,
-                                                                     &errCode)) {
+                                                                     &errCode);
+#pragma GCC diagnostic pop
+                       if (!ok) {
                                data = NULL;
                        }
                        CFRelease(url);
@@ -1018,7 +1017,8 @@ _SC_CFMachPortCreateWithPort(const char           *portDescription,
                                                       portDescription);
                }
                crash_info = _SC_cfstring_to_cstring(err, NULL, 0, kCFStringEncodingASCII);
-               CFRelease(err);
+               if (err != NULL) CFRelease(err);
+
 
                err = CFStringCreateWithFormat(NULL,
                                               NULL,
@@ -1197,7 +1197,7 @@ _SC_logMachPortReferences(const char *str, mach_port_t port)
                static int      is_configd      = -1;
 
                if (is_configd == -1) {
-                       is_configd = (strcmp(getprogname(), "configd") == 0);
+                       is_configd = (strcmp(getprogname(), _SC_SERVER_PROG) == 0);
                }
                if (is_configd == 1) {
                        // if "configd", add indication if this is the M[ain] or [P]lugin thread
@@ -1359,11 +1359,11 @@ asm(".desc ___crashreporter_info__, 0x10");
 static Boolean
 _SC_SimulateCrash(const char *crash_info, CFStringRef notifyHeader, CFStringRef notifyMessage)
 {
-       Boolean ok                                                                                      = FALSE;
+       Boolean ok      = FALSE;
 
 #if ! TARGET_IPHONE_SIMULATOR
        static bool     (*dyfunc_SimulateCrash)(pid_t, mach_exception_data_type_t, CFStringRef) = NULL;
-       static void     *image                                                                                  = NULL;
+       static void     *image                                                                  = NULL;
 
        if ((dyfunc_SimulateCrash == NULL) && (image == NULL)) {
                const char      *framework      = "/System/Library/PrivateFrameworks/CrashReporterSupport.framework/CrashReporterSupport";
@@ -1394,28 +1394,30 @@ _SC_SimulateCrash(const char *crash_info, CFStringRef notifyHeader, CFStringRef
                CFRelease(str);
        }
 
-#if    TARGET_OS_EMBEDDED && !TARGET_OS_EMBEDDED_OTHER && !defined(DO_NOT_INFORM)
-       if (ok) {
+#if    TARGET_OS_EMBEDDED && !defined(DO_NOT_INFORM)
+       if (ok && (notifyHeader != NULL) && (notifyMessage != NULL)) {
                static Boolean  warned  = FALSE;
 
                if (!warned) {
-                       notifyMessage = CFStringCreateWithFormat(NULL,
-                                                                NULL,
-                                                                CFSTR("%@\n\nPlease collect the crash report and file a Radar."),
-                                                                notifyMessage);
+                       CFStringRef     displayMessage;
+
+                       displayMessage = CFStringCreateWithFormat(NULL,
+                                                                 NULL,
+                                                                 CFSTR("%@\n\nPlease collect the crash report and file a Radar."),
+                                                                 notifyMessage);
                        CFUserNotificationDisplayNotice(0,
                                                        kCFUserNotificationStopAlertLevel,
                                                        NULL,
                                                        NULL,
                                                        NULL,
                                                        notifyHeader,
-                                                       notifyMessage,
+                                                       displayMessage,
                                                        NULL);
-                       CFRelease(notifyMessage);
+                       CFRelease(displayMessage);
                        warned = TRUE;
                }
        }
-#endif // TARGET_OS_EMBEDDED && !TARGET_OS_EMBEDDED_OTHER && !defined(DO_NOT_INFORM)
+#endif // TARGET_OS_EMBEDDED && !defined(DO_NOT_INFORM)
 #endif /* ! TARGET_IPHONE_SIMULATOR */
 
        return ok;
@@ -1447,3 +1449,41 @@ _SC_crash(const char *crash_info, CFStringRef notifyHeader, CFStringRef notifyMe
        __crashreporter_info__ = NULL;
        return;
 }
+
+
+Boolean
+_SC_getconninfo(int socket, struct sockaddr_storage *src_addr, struct sockaddr_storage *dest_addr, int *if_index, uint32_t *flags)
+{
+       struct so_cinforeq      request;
+
+       memset(&request, 0, sizeof(request));
+
+       if (src_addr != NULL) {
+               memset(src_addr, 0, sizeof(*src_addr));
+               request.scir_src = (struct sockaddr *)src_addr;
+               request.scir_src_len = sizeof(*src_addr);
+       }
+
+       if (dest_addr != NULL) {
+               memset(dest_addr, 0, sizeof(*dest_addr));
+               request.scir_dst = (struct sockaddr *)dest_addr;
+               request.scir_dst_len = sizeof(*dest_addr);
+       }
+
+       if (ioctl(socket, SIOCGCONNINFO, &request) != 0) {
+               SCLog(TRUE, LOG_WARNING, CFSTR("SIOCGCONNINFO failed: %s"), strerror(errno));
+               return FALSE;
+       }
+
+       if (if_index != NULL) {
+               *if_index = 0;
+               *if_index = request.scir_ifindex;
+       }
+
+       if (flags != NULL) {
+               *flags = 0;
+               *flags = request.scir_flags;
+       }
+
+       return TRUE;
+}
index 7682d42d41f6078bfa3d4d4e39e6eeebfe03364b..66148ea92b0131fe5c4437daa2290f4d3b990018 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2002, 2004, 2005, 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2001, 2002, 2004, 2005, 2008, 2012 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -106,11 +106,11 @@ DHCPInfoGetLeaseStartTime (CFDictionaryRef        info)           __OSX_AVAILABLE_STARTING(__MAC
                NULL if the lease is infinite i.e. has no expiration, or the
                configuration method is not DHCP. An infinite lease can be determined
                by a non-NULL lease start time (see DHCPInfoGetLeaseStartTime above).
-        
+
                The return value must NOT be released.
 */
 CFDateRef
-DHCPInfoGetLeaseExpirationTime (CFDictionaryRef        info)           __OSX_AVAILABLE_STARTING(__MAC_10_8,__IPHONE_NA);
+DHCPInfoGetLeaseExpirationTime (CFDictionaryRef        info)           __OSX_AVAILABLE_STARTING(__MAC_10_8,__IPHONE_6_0/*SPI*/);
 
 __END_DECLS
 
index a32aa7fe6794784de58d849da51e2855e2f59417..b81fbfc2a31f0b9d90628e48ff8f101b67d87ae2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2004, 2006, 2009-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2004, 2006, 2009-2011, 2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
index af5a5cc1fd83d49b04391ed30317a4fbf3743d63..40acd63e98deab1aa5ae37f1fd9c77552f490664 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2001, 2004, 2005, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2004, 2005, 2010, 2011, 2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -109,6 +109,7 @@ typedef void (*SCDynamicStoreDisconnectCallBack)    (
                                                         );
 
 
+
 __BEGIN_DECLS
 
 /*!
index 2342887f6bf552cffa91404090f382a720ed744c..b90bb1a53eb8cb6609e1bf6ad3fa788bc153f3c3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2007, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2007, 2009, 2010, 2012, 2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -72,6 +72,7 @@ __setPrefsConfiguration(SCPreferencesRef      prefs,
                        CFDictionaryRef         config,
                        Boolean                 keepInactive)
 {
+       CFDictionaryRef         curConfig;
        CFMutableDictionaryRef  newConfig       = NULL;
        Boolean                 ok;
 
@@ -80,13 +81,13 @@ __setPrefsConfiguration(SCPreferencesRef    prefs,
                return FALSE;
        }
 
+       curConfig = SCPreferencesPathGetValue(prefs, path);
+
        if (config != NULL) {
                newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config);
        }
 
        if (keepInactive) {
-               CFDictionaryRef curConfig;
-
                if (config == NULL) {
                        newConfig = CFDictionaryCreateMutable(NULL,
                                                              0,
@@ -94,7 +95,6 @@ __setPrefsConfiguration(SCPreferencesRef      prefs,
                                                              &kCFTypeDictionaryValueCallBacks);
                }
 
-               curConfig = SCPreferencesPathGetValue(prefs, path);
                if (isA_CFDictionary(curConfig) && CFDictionaryContainsKey(curConfig, kSCResvInactive)) {
                        // if currently disabled
                        CFDictionarySetValue(newConfig, kSCResvInactive, kCFBooleanTrue);
@@ -105,7 +105,11 @@ __setPrefsConfiguration(SCPreferencesRef   prefs,
        }
 
        // set new configuration
-       if (newConfig != NULL) {
+       if (_SC_CFEqual(curConfig, newConfig)) {
+               // if no change
+               if (newConfig != NULL) CFRelease(newConfig);
+               ok = TRUE;
+       } else if (newConfig != NULL) {
                // if new configuration (or we are preserving a disabled state)
                ok = SCPreferencesPathSetValue(prefs, path, newConfig);
                CFRelease(newConfig);
@@ -168,7 +172,11 @@ __setPrefsEnabled(SCPreferencesRef      prefs,
        }
 
        // set new configuration
-       if (newConfig != NULL) {
+       if (_SC_CFEqual(curConfig, newConfig)) {
+               // if no change
+               if (newConfig != NULL) CFRelease(newConfig);
+               ok = TRUE;
+       } else if (newConfig != NULL) {
                // if updated configuration (or we are establishing as disabled)
                ok = SCPreferencesPathSetValue(prefs, path, newConfig);
                CFRelease(newConfig);
@@ -203,7 +211,10 @@ __copyTemplates()
                return NULL;
        }
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated"
        ok = CFURLCreateDataAndPropertiesFromResource(NULL, url, &xmlTemplates, NULL, NULL, NULL);
+#pragma GCC diagnostic pop
        CFRelease(url);
        if (!ok || (xmlTemplates == NULL)) {
                return NULL;
index ba253f07a72dee446486f19c9478d960cfee3437..3075883ea0b40e818fea9d1a5208ff2347326414 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -73,6 +73,9 @@ typedef struct {
        // name
        CFStringRef             name;
 
+       // external identifiers
+       CFMutableDictionaryRef  externalIDs;
+
 } SCNetworkServicePrivate, *SCNetworkServicePrivateRef;
 
 
@@ -143,6 +146,7 @@ typedef struct {
        uint64_t                entryID;
        CFMutableDictionaryRef  overrides;
        Boolean                 modemIsV92;
+       CFStringRef             prefix;
        CFNumberRef             type;
        CFNumberRef             unit;
        struct {
@@ -158,8 +162,8 @@ typedef struct {
        Boolean                 supportsBond;
        struct {
                CFArrayRef              interfaces;
-               CFDictionaryRef         options;
                CFNumberRef             mode;
+               CFDictionaryRef         options;
        } bond;
 
        // for Bridge interfaces
@@ -221,13 +225,13 @@ CFArrayRef
 __SCNetworkInterfaceCopyDeepConfiguration       (SCNetworkSetRef       set,
                                                 SCNetworkInterfaceRef  interface);
 
-#if    !TARGET_OS_EMBEDDED && !TARGET_IPHONE_SIMULATOR
+#if    !TARGET_OS_IPHONE
 CFStringRef
 __SCNetworkInterfaceCopyXLocalizedDisplayName  (SCNetworkInterfaceRef  interface);
 
 CFStringRef
 __SCNetworkInterfaceCopyXNonLocalizedDisplayName(SCNetworkInterfaceRef interface);
-#endif // !TARGET_OS_EMBEDDED && !TARGET_IPHONE_SIMULATOR
+#endif // !TARGET_OS_IPHONE
 
 int
 __SCNetworkInterfaceCreateCapabilities         (SCNetworkInterfaceRef  interface,
index fb1987bf26fe730e5594ac437186183e3f6791aa..ddc8ba74a7153411f6594e2f41546cee12669fdc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2005-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -192,6 +192,14 @@ _SCNetworkInterfaceCopyActive                              (SCDynamicStoreRef              store,
 CFArrayRef /* of SCNetworkInterfaceRef's */
 _SCNetworkInterfaceCopyAllWithPreferences              (SCPreferencesRef               prefs)          __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_5_0/*SPI*/);
 
+/*!
+       @function _SCNetworkInterfaceCopyBTPANInterface
+       @discussion Returns the SCNetworkInterface associated with the BT-PAN interface
+       @result The BT-PAN interface; NULL if the interface is not (yet) known.
+ */
+SCNetworkInterfaceRef
+_SCNetworkInterfaceCopyBTPANInterface                  (void)                                          __OSX_AVAILABLE_STARTING(__MAC_10_8/*FIXME*/,__IPHONE_NA);
+
 /*!
        @function _SCNetworkInterfaceCopySlashDevPath
        @discussion Returns the /dev pathname for the interface.
@@ -311,6 +319,16 @@ _SCNetworkInterfaceGetConfigurationAction          (SCNetworkInterfaceRef          interface)      __
 CFDataRef
 _SCNetworkInterfaceGetHardwareAddress                  (SCNetworkInterfaceRef          interface)      __OSX_AVAILABLE_STARTING(__MAC_10_5,__IPHONE_2_0);
 
+/*!
+       @function _SCNetworkInterfaceGetIOInterfaceNamePrefix
+       @discussion Returns the IOInterfaceNamePrefix for the interface.
+       @param interface The network interface.
+       @result The IOInterfaceNamePrefix associated with the interface;
+               NULL if no IOInterfaceNamePrefix is available.
+ */
+CFStringRef
+_SCNetworkInterfaceGetIOInterfaceNamePrefix            (SCNetworkInterfaceRef          interface)      __OSX_AVAILABLE_STARTING(__MAC_10_8,__IPHONE_6_0);
+
 /*!
        @function _SCNetworkInterfaceGetIOInterfaceType
        @discussion Returns the IOInterfaceType for the interface.
@@ -325,7 +343,7 @@ _SCNetworkInterfaceGetIOInterfaceType                       (SCNetworkInterfaceRef          interface)      __OSX
        @discussion Returns the IOInterfaceUnit for the interface.
        @param interface The network interface.
        @result The IOInterfaceUnit associated with the interface;
-               NULL if no IOLocation is available.
+               NULL if no IOInterfaceUnit is available.
  */
 CFNumberRef
 _SCNetworkInterfaceGetIOInterfaceUnit                  (SCNetworkInterfaceRef          interface)      __OSX_AVAILABLE_STARTING(__MAC_10_5,__IPHONE_2_0);
@@ -415,6 +433,15 @@ _SCNetworkInterfaceIsModemV92                              (SCNetworkInterfaceRef          interface)      __OSX_AVAILA
 Boolean
 _SCNetworkInterfaceIsTethered                          (SCNetworkInterfaceRef          interface)      __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_3_0);
 
+/*!
+       @function _SCNetworkInterfaceIsThunderbolt
+       @discussion Identifies if a network interface is a Thunderbolt device
+       @param interface The network interface.
+       @result TRUE if the interface is a Thunderbolt device.
+ */
+Boolean
+_SCNetworkInterfaceIsThunderbolt                       (SCNetworkInterfaceRef          interface)      __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
+
 /*!
        @function _SCNetworkInterfaceIsPhysicalEthernet
        @discussion Indicates whether a network interface is a real ethernet interface i.e. one with an ethernet PHY.
@@ -779,6 +806,30 @@ SCNetworkServiceSetPrimaryRank                             (SCNetworkServiceRef            service,
 Boolean
 _SCNetworkServiceIsVPN                                 (SCNetworkServiceRef            service)        __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_4_0);
 
+/*!
+       @function SCNetworkServiceSetExternalID
+       @discussion Set the external identifier for a network service.
+       @param service A reference to the network service.
+       @param identifierDomain A service can have multiple external identifiers. This string specifies which external identifier to set.
+       @param identifier The new external identifier to assign to the network service.
+       @result Returns TRUE if the external identifier was set successfully, FALSE if an error occurred.
+ */
+Boolean
+SCNetworkServiceSetExternalID                          (SCNetworkServiceRef            service,
+                                                        CFStringRef                    identifierDomain,
+                                                        CFStringRef identifier);
+
+/*!
+       @function SCNetworkServiceCopyExternalID
+       @discussion Copy the external identifier for a network service.
+       @param service The network service.
+       @param identifierDomain A service can have multiple external identifiers. This string specifies which external identifier to copy.
+       @result Returns the service's external identifier, or NULL if the service does not have an external identifier in the given domain.
+*/
+CFStringRef
+SCNetworkServiceCopyExternalID                         (SCNetworkServiceRef            service,
+                                                        CFStringRef                    identifierDomain);
+
 #pragma mark -
 #pragma mark SCNetworkSet configuration (SPI)
 
@@ -795,6 +846,17 @@ isA_SCNetworkSet(CFTypeRef obj)
 }
 
 
+/*!
+       @function SCNetworkSetCopyAvailableInterfaces
+       @discussion Returns all available interfaces for the set.
+               The interfaces excludes those of bond and bridge members.
+       @param set The network set.
+       @result The list of SCNetworkInterfaces.
+               You must release the returned value.
+ */
+CFArrayRef
+SCNetworkSetCopyAvailableInterfaces                    (SCNetworkSetRef                set)            __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/);
+
 /*!
        @function SCNetworkSetEstablishDefaultConfiguration
        @discussion Updates a network set by adding services for
@@ -861,5 +923,85 @@ Boolean
 SCNetworkSetSetSelectedVPNService                      (SCNetworkSetRef                set,
                                                         SCNetworkServiceRef            service)        __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_4_0);
 
+/*!
+       @group VPN Service configuration
+ */
+
+#pragma mark -
+#pragma mark VPN Service configuration
+
+typedef SCNetworkServiceRef VPNServiceRef;
+
+/*!
+       @function VPNServiceCopyAllMatchingExternalID
+       @discussion Copy the VPN services with the given external identifier.
+       @param prefs A reference to the prefs where the VPN services are stored.
+       @param identifierDomain A service can have multiple external identifiers. This string specifies which one to match with the given identifier.
+       @param identifier The external identifier of the desired services.
+       @result A array of references to the VPN services with the given identifier, or NULL if no such service exists
+ */
+CFArrayRef
+VPNServiceCopyAllMatchingExternalID            (SCPreferencesRef               prefs,
+                                                CFStringRef                    identifierDomain,
+                                                CFStringRef identifier)                __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/);
+
+/*!
+       @function VPNServiceCopyAll
+       @discussion Copy all VPN services.
+       @param prefs A reference to the prefs where the VPN services are stored.
+       @result An array containing VPNServiceRefs for all the VPN services.
+ */
+CFArrayRef
+VPNServiceCopyAll                              (SCPreferencesRef               prefs)  __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/);
+
+/*!
+       @function VPNServiceCopyAppRuleIDs
+       @discussion Copy all the app rule identifiers for a VPN service.
+       @param service A reference to the VPN service.
+       @result An array of CFStringRefs, each string containing the identifier of a app rule in the given service.
+ */
+CFArrayRef
+VPNServiceCopyAppRuleIDs                       (VPNServiceRef                  service)        __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/);
+
+/*!
+       @function VPNServiceSetAppRule
+       @discussion Add or modify an app rule in a VPN service. The ruleSettings dictionary must contain one of the following keys:
+               <pre>kSCValNetVPNAppRuleExecutableMatch</pre>
+               <pre>kSCValNetVPNAppRuleAccountIdentifierMatch</pre>
+       The ruleSettings dictionary may also contain the following keys:
+               <pre>kSCValNetVPNAppRuleDNSDomainMatch</pre>
+       See SCSchemaDefinitionsPrivate.h for more details.
+       @param service A reference to the VPN service.
+       @param ruleIdentifier The identifier of the new app rule.
+       @param ruleSettings The settings for the new app rule. See the dictionary keys defined above.
+       @result TRUE if the app rule was set successfully, FALSE if an error occurred.
+ */
+Boolean
+VPNServiceSetAppRule                           (VPNServiceRef                  service,
+                                                CFStringRef                    ruleIdentifier,
+                                                CFDictionaryRef                ruleSettings)   __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/);
+
+/*!
+       @function VPNServiceCopyAppRule
+       @discussion Copy the settings for a app rule in a VPN service.
+       @param service The app tunnel service.
+       @param ruleIdentifier The ID of the app rule.
+       @result The rule settings, or NULL if the app rule could not be found.
+ */
+CFDictionaryRef
+VPNServiceCopyAppRule                          (VPNServiceRef                  service,
+                                                CFStringRef                    ruleIdentifier) __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/);
+
+/*!
+       @function VPNServiceRemoveAppRule
+       @discussion Remove an app rule from a VPN service.
+       @param service The VPN service.
+       @param ruleIdentifier The ID of the app rule to remove.
+       @result Returns TRUE if the app rule was removed successfully; FALSE otherwise.
+ */
+Boolean
+VPNServiceRemoveAppRule                                (VPNServiceRef                  service,
+                                                CFStringRef                    ruleIdentifier) __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/);
+
 __END_DECLS
 #endif /* _SCNETWORKCONFIGURATIONPRIVATE_H */
index e54ea073c63ad8df05f8193ace89ef875a89144c..067c14e3a2ad975dde65f4521237441bf418ec87 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003-2012 Apple Inc. All rights reserved.
+ * Copyright (c) 2003-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -44,6 +44,8 @@
 #include <SystemConfiguration/SystemConfiguration.h>
 #include <SystemConfiguration/SCPrivate.h>
 #include <SystemConfiguration/SCValidation.h>
+#include <SystemConfiguration/VPNAppLayerPrivate.h>
+#include <SystemConfiguration/VPNTunnel.h>
 
 #if    !TARGET_OS_IPHONE
 #include <Security/Security.h>
 #include <net/if.h>
 #include <mach/mach.h>
 #include <bsm/audit.h>
+#include <bsm/libbsm.h>
+#include <sandbox.h>
 
 #include <ppp/ppp_msg.h>
 #include "pppcontroller.h"
 #include <ppp/pppcontroller_types.h>
 
+#ifndef        PPPCONTROLLER_SERVER_PRIV
+#define        PPPCONTROLLER_SERVER_PRIV       PPPCONTROLLER_SERVER
+#endif // !PPPCONTROLLER_SERVER_PRIV
 
 
+#include "SCNetworkConnectionInternal.h"
+
 static int             debug                   = 0;
 static pthread_once_t  initialized             = PTHREAD_ONCE_INIT;
 static pthread_mutex_t scnc_lock               = PTHREAD_MUTEX_INITIALIZER;
 static mach_port_t     scnc_server             = MACH_PORT_NULL;
+static char            *scnc_server_name       = NULL;
 
 
 typedef struct {
@@ -90,9 +100,13 @@ typedef struct {
 
        /* client info (if we are proxying for another process */
        mach_port_t                     client_audit_session;
+       audit_token_t                   client_audit_token;
+       mach_port_t                     client_bootstrap_port;
        uid_t                           client_uid;
        gid_t                           client_gid;
        pid_t                           client_pid;
+       uuid_t                          client_uuid;
+       CFStringRef                     client_bundle_id;
 
        /* ref to PPP controller for control messages */
        mach_port_t                     session_port;
@@ -115,6 +129,14 @@ typedef struct {
        dispatch_queue_t                dispatchQueue;
        dispatch_source_t               dispatchSource;
 
+       SCNetworkConnectionType         type;
+       Boolean                         on_demand;
+       CFDictionaryRef                 on_demand_info;
+       CFDictionaryRef                 on_demand_user_options;
+       CFStringRef                     on_demand_required_probe;
+
+       /* Flow Divert support info */
+       CFDictionaryRef                 flow_divert_token_params;
 } SCNetworkConnectionPrivate, *SCNetworkConnectionPrivateRef;
 
 
@@ -136,7 +158,7 @@ __SCNetworkConnectionCopyDescription(CFTypeRef cf)
        CFStringAppendFormat(result, NULL, CFSTR("<SCNetworkConnection, %p [%p]> {"), cf, allocator);
        CFStringAppendFormat(result, NULL, CFSTR("service = %p"), connectionPrivate->service);
        if (connectionPrivate->session_port != MACH_PORT_NULL) {
-               CFStringAppendFormat(result, NULL, CFSTR(", server port = %p"), connectionPrivate->session_port);
+               CFStringAppendFormat(result, NULL, CFSTR(", server port = 0x%x"), connectionPrivate->session_port);
        }
        CFStringAppendFormat(result, NULL, CFSTR("}"));
 
@@ -159,6 +181,17 @@ __SCNetworkConnectionDeallocate(CFTypeRef cf)
                                   -1);
        }
 
+       if (connectionPrivate->client_bootstrap_port != MACH_PORT_NULL) {
+               mach_port_mod_refs(mach_task_self(),
+                                  connectionPrivate->client_bootstrap_port,
+                                  MACH_PORT_RIGHT_SEND,
+                                  -1);
+       }
+
+       if (connectionPrivate->client_bundle_id != NULL) {
+               CFRelease(connectionPrivate->client_bundle_id);
+       }
+
        if (connectionPrivate->rls != NULL) {
                CFRunLoopSourceInvalidate(connectionPrivate->rls);
                CFRelease(connectionPrivate->rls);
@@ -185,7 +218,25 @@ __SCNetworkConnectionDeallocate(CFTypeRef cf)
        if (connectionPrivate->rlsContext.release != NULL)
                (*connectionPrivate->rlsContext.release)(connectionPrivate->rlsContext.info);
 
-       CFRelease(connectionPrivate->service);
+       if (connectionPrivate->service != NULL) {
+               CFRelease(connectionPrivate->service);
+       }
+
+       if (connectionPrivate->on_demand_info != NULL) {
+               CFRelease(connectionPrivate->on_demand_info);
+       }
+
+       if (connectionPrivate->on_demand_user_options != NULL) {
+               CFRelease(connectionPrivate->on_demand_user_options);
+       }
+
+       if (connectionPrivate->on_demand_required_probe != NULL) {
+               CFRelease(connectionPrivate->on_demand_required_probe);
+       }
+
+       if (connectionPrivate->flow_divert_token_params != NULL) {
+               CFRelease(connectionPrivate->flow_divert_token_params);
+       }
 
        return;
 }
@@ -212,6 +263,7 @@ childForkHandler()
        /* the process has forked (and we are the child process) */
 
        scnc_server = MACH_PORT_NULL;
+       scnc_server_name = NULL;
        return;
 }
 
@@ -243,18 +295,84 @@ __SCNetworkConnectionInitialize(void)
 static Boolean
 __SCNetworkConnectionReconnectNotifications(SCNetworkConnectionRef connection);
 
+#define SC_NETWORK_CONNECTION_QUEUE "SCNetworkConnectionQueue"
+
+static dispatch_queue_t
+__SCNetworkConnectionQueue()
+{
+       static dispatch_once_t  once;
+       static dispatch_queue_t q;
+
+       dispatch_once(&once, ^{
+               q = dispatch_queue_create(SC_NETWORK_CONNECTION_QUEUE, NULL);
+       });
+
+       return q;
+}
+
+
+static void
+__SCNetworkConnectionCallBackRunLoopPerform(SCNetworkConnectionRef connection,
+                                           CFRunLoopRef rl,
+                                           CFStringRef rl_mode,
+                                           SCNetworkConnectionCallBack rlsFunction,
+                                           void (*context_release)(const void *),
+                                           void *context_info)
+{
+       SCNetworkConnectionStatus       nc_status       = kSCNetworkConnectionInvalid;
+
+       nc_status = SCNetworkConnectionGetStatus(connection);
+       CFRunLoopPerformBlock(rl, rl_mode,
+                             ^{
+                                     (*rlsFunction)(connection, nc_status, context_info);
+                                     if ((context_release != NULL) && (context_info != NULL)) {
+                                             (*context_release)(context_info);
+                                     }
+                                     CFRelease(rl);
+                                     CFRelease(rl_mode);
+                                     CFRelease(connection);
+                             });
+       CFRunLoopWakeUp(rl);
+       return;
+}
+
+static void
+__SCNetworkConnectionCallBackDispatchPerform(SCNetworkConnectionRef connection,
+                                            dispatch_queue_t q,
+                                            SCNetworkConnectionCallBack rlsFunction,
+                                            void (*context_release)(const void *),
+                                            void *context_info)
+{
+       SCNetworkConnectionStatus       nc_status       = kSCNetworkConnectionInvalid;
+
+       nc_status = SCNetworkConnectionGetStatus(connection);
+       dispatch_async(q,
+                      ^{
+                              (*rlsFunction)(connection, nc_status, context_info);
+                              if ((context_release != NULL) && (context_info != NULL)) {
+                                      (*context_release)(context_info);
+                              }
+                              dispatch_release(q);
+                              CFRelease(connection);
+                      });
+       return;
+}
+
 
 static void
 __SCNetworkConnectionCallBack(CFMachPortRef port, void * msg, CFIndex size, void * info)
 {
        mach_no_senders_notification_t  *buf                    = msg;
        mach_msg_id_t                   msgid                   = buf->not_header.msgh_id;
-
+       boolean_t                       exec_async              = FALSE;
        SCNetworkConnectionRef          connection              = (SCNetworkConnectionRef)info;
        SCNetworkConnectionPrivateRef   connectionPrivate       = (SCNetworkConnectionPrivateRef)connection;
        void                            *context_info;
        void                            (*context_release)(const void *);
+       CFRunLoopRef                    rl                      = NULL;
+       CFStringRef                     rl_mode;
        SCNetworkConnectionCallBack     rlsFunction             = NULL;
+       dispatch_queue_t                q                       = NULL;
        SCNetworkConnectionStatus       nc_status               = kSCNetworkConnectionInvalid;
 
        if (msgid == MACH_NOTIFY_NO_SENDERS) {
@@ -267,12 +385,14 @@ __SCNetworkConnectionCallBack(CFMachPortRef port, void * msg, CFIndex size, void
 
        if (!connectionPrivate->scheduled) {
                // if not currently scheduled
-               goto doit;
+               pthread_mutex_unlock(&connectionPrivate->lock);
+               return;
        }
 
        rlsFunction = connectionPrivate->rlsFunction;
        if (rlsFunction == NULL) {
-               goto doit;
+               pthread_mutex_unlock(&connectionPrivate->lock);
+               return;
        }
 
        if ((connectionPrivate->rlsContext.retain != NULL) && (connectionPrivate->rlsContext.info != NULL)) {
@@ -283,18 +403,54 @@ __SCNetworkConnectionCallBack(CFMachPortRef port, void * msg, CFIndex size, void
                context_release = NULL;
        }
 
-    doit :
+       // Do we need to spin a new thread? (either we are running on the main
+       // dispatch queue or main runloop)
+       if (connectionPrivate->rlList == NULL) {
+               // this is the case if we are performing a callback on a dispatch queue
+               q = connectionPrivate->dispatchQueue;
+               if (q == dispatch_get_main_queue()) {
+                       exec_async = TRUE;
+               }
+       } else {
+               rl = CFRunLoopGetCurrent();
+               if (rl == CFRunLoopGetMain()) {
+                       exec_async = TRUE;
+               }
+       }
 
+       CFRetain(connection);
        pthread_mutex_unlock(&connectionPrivate->lock);
 
-       if (rlsFunction == NULL) {
+       if (exec_async == FALSE) {
+               nc_status = SCNetworkConnectionGetStatus(connection);
+               (*rlsFunction)(connection, nc_status, context_info);
+               if ((context_release != NULL) && (context_info != NULL)) {
+                       (*context_release)(context_info);
+               }
+               CFRelease(connection);
                return;
        }
 
-       nc_status = SCNetworkConnectionGetStatus(connection);
-       (*rlsFunction)(connection, nc_status, context_info);
-       if ((context_release != NULL) && (context_info != NULL)) {
-               (*context_release)(context_info);
+       if (connectionPrivate->rlList == NULL) {
+               assert(q != NULL);
+               dispatch_retain(q);
+               dispatch_async(__SCNetworkConnectionQueue(),
+                              ^{__SCNetworkConnectionCallBackDispatchPerform(connection,
+                                                                             q,
+                                                                             rlsFunction,
+                                                                             context_release,
+                                                                             context_info);});
+       } else {
+               assert(rl != NULL);
+               CFRetain(rl);
+               rl_mode = CFRunLoopCopyCurrentMode(rl);
+               dispatch_async(__SCNetworkConnectionQueue(),
+                              ^{__SCNetworkConnectionCallBackRunLoopPerform(connection,
+                                                                            rl,
+                                                                            rl_mode,
+                                                                            rlsFunction,
+                                                                            context_release,
+                                                                            context_info);});
        }
 
        return;
@@ -345,12 +501,17 @@ __SCNetworkConnectionCreatePrivate(CFAllocatorRef         allocator,
        pthread_mutex_init(&connectionPrivate->lock, NULL);
 
        /* save the service */
-       connectionPrivate->service = CFRetain(service);
+       if (service != NULL) {
+               connectionPrivate->service = CFRetain(service);
+       }
 
        connectionPrivate->client_audit_session = MACH_PORT_NULL;
+       connectionPrivate->client_bootstrap_port = MACH_PORT_NULL;
        connectionPrivate->client_uid = geteuid();
        connectionPrivate->client_gid = getegid();
        connectionPrivate->client_pid = getpid();
+       connectionPrivate->client_bundle_id = NULL;
+       uuid_clear(connectionPrivate->client_uuid);
 
        connectionPrivate->rlsFunction = callout;
 
@@ -361,6 +522,8 @@ __SCNetworkConnectionCreatePrivate(CFAllocatorRef           allocator,
                }
        }
 
+       connectionPrivate->type = kSCNetworkConnectionTypeUnknown;
+
        /* success, return the connection reference */
        return connectionPrivate;
 
@@ -383,12 +546,12 @@ __SCNetworkConnectionServerPort(kern_return_t *status)
 
 #ifdef BOOTSTRAP_PRIVILEGED_SERVER
        *status = bootstrap_look_up2(bootstrap_port,
-                                    PPPCONTROLLER_SERVER,
+                                    __SCNetworkConnectionGetControllerPortName(),
                                     &server,
                                     0,
                                     BOOTSTRAP_PRIVILEGED_SERVER);
 #else  // BOOTSTRAP_PRIVILEGED_SERVER
-       *status = bootstrap_look_up(bootstrap_port, PPPCONTROLLER_SERVER, &server);
+       *status = bootstrap_look_up(bootstrap_port, __SCNetworkConnectionGetControllerPortName(), &server);
 #endif // BOOTSTRAP_PRIVILEGED_SERVER
 
        switch (*status) {
@@ -410,11 +573,41 @@ __SCNetworkConnectionServerPort(kern_return_t *status)
                        break;
        }
 
+       scnc_server_name = NULL;                /* reset pppcontroller server */
        return MACH_PORT_NULL;
 }
 
+static mach_port_t
+__SCNetworkConnectionGetCurrentServerPort(void)
+{
+       return scnc_server;
+}
+
+static mach_port_t
+__SCNetworkConnectionRefreshServerPort(mach_port_t current_server, int *mach_result)
+{
+       mach_port_t new_server;
+
+       pthread_mutex_lock(&scnc_lock);
+       if (scnc_server != MACH_PORT_NULL) {
+               if (current_server == scnc_server) {
+                       scnc_server_name = NULL;
+                       // if the server we tried returned the error
+                       (void)mach_port_deallocate(mach_task_self(), scnc_server);
+                       scnc_server = __SCNetworkConnectionServerPort(mach_result);
+               } else {
+                       // another thread has refreshed the server port
+               }
+       } else {
+               scnc_server = __SCNetworkConnectionServerPort(mach_result);
+       }
+       new_server = scnc_server;
+       pthread_mutex_unlock(&scnc_lock);
+
+       return new_server;
+}
 
-#if    ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 50000)) && !TARGET_IPHONE_SIMULATOR
+#if    ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 50000)) && (!TARGET_IPHONE_SIMULATOR || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 70000))
 #define        HAVE_PPPCONTROLLER_ATTACHWITHAUDITSESSION
 #endif
 
@@ -423,7 +616,6 @@ __SCNetworkConnectionServerPort(kern_return_t *status)
 #define        HAVE_PPPCONTROLLER_ATTACHWITHPROXY
 #endif
 
-
 static mach_port_t
 __SCNetworkConnectionSessionPort(SCNetworkConnectionPrivateRef connectionPrivate)
 {
@@ -434,7 +626,7 @@ __SCNetworkConnectionSessionPort(SCNetworkConnectionPrivateRef connectionPrivate
        mach_port_t     oldNotify       = MACH_PORT_NULL;
        int             retry           = 0;
        int             sc_status       = kSCStatusFailed;
-       mach_port_t     server          = scnc_server;
+       mach_port_t     server          = __SCNetworkConnectionGetCurrentServerPort();
        kern_return_t   status          = KERN_SUCCESS;
 
 #ifdef HAVE_PPPCONTROLLER_ATTACHWITHAUDITSESSION
@@ -445,6 +637,11 @@ __SCNetworkConnectionSessionPort(SCNetworkConnectionPrivateRef connectionPrivate
                return connectionPrivate->session_port;
        }
 
+       if (connectionPrivate->service == NULL) {
+               sc_status = kSCStatusConnectionNoService;
+               goto done;
+       }
+
        if (!_SCSerializeString(SCNetworkServiceGetServiceID(connectionPrivate->service), &dataRef, &data, &dataLen)) {
                goto done;
        }
@@ -490,6 +687,7 @@ __SCNetworkConnectionSessionPort(SCNetworkConnectionPrivateRef connectionPrivate
                if (server != MACH_PORT_NULL) {
 #ifdef HAVE_PPPCONTROLLER_ATTACHWITHPROXY
                        if ((connectionPrivate->client_audit_session == MACH_PORT_NULL) &&
+                           (connectionPrivate->client_bootstrap_port == MACH_PORT_NULL) &&
                            (connectionPrivate->client_uid == geteuid()) &&
                            (connectionPrivate->client_gid == getegid()) &&
                            (connectionPrivate->client_pid == getpid())
@@ -508,6 +706,7 @@ __SCNetworkConnectionSessionPort(SCNetworkConnectionPrivateRef connectionPrivate
 #ifdef HAVE_PPPCONTROLLER_ATTACHWITHPROXY
                        } else {
                                mach_port_t     client_au_session;
+                               mach_port_t     client_bootstrap_port;
 
                                if (connectionPrivate->client_audit_session == MACH_PORT_NULL) {
                                        client_au_session = au_session;
@@ -515,10 +714,16 @@ __SCNetworkConnectionSessionPort(SCNetworkConnectionPrivateRef connectionPrivate
                                        client_au_session = connectionPrivate->client_audit_session;
                                }
 
+                               if (connectionPrivate->client_bootstrap_port == MACH_PORT_NULL) {
+                                       client_bootstrap_port = bootstrap_port;
+                               } else {
+                                       client_bootstrap_port = connectionPrivate->client_bootstrap_port;
+                               }
+
                                status = pppcontroller_attach_proxy(server,
                                                                    data,
                                                                    dataLen,
-                                                                   bootstrap_port,
+                                                                   client_bootstrap_port,
                                                                    notify_port,
                                                                    client_au_session,
                                                                    connectionPrivate->client_uid,
@@ -571,21 +776,7 @@ __SCNetworkConnectionSessionPort(SCNetworkConnectionPrivateRef connectionPrivate
                        }
                }
 
-               pthread_mutex_lock(&scnc_lock);
-               if (scnc_server != MACH_PORT_NULL) {
-                       if (server == scnc_server) {
-                               // if the server we tried returned the error
-                               (void)mach_port_deallocate(mach_task_self(), scnc_server);
-                               scnc_server = __SCNetworkConnectionServerPort(&sc_status);
-                       } else {
-                               // another thread has refreshed the server port
-                       }
-               } else {
-                       scnc_server = __SCNetworkConnectionServerPort(&sc_status);
-               }
-               server = scnc_server;
-               pthread_mutex_unlock(&scnc_lock);
-
+               server = __SCNetworkConnectionRefreshServerPort(server, &sc_status);
                if (server == MACH_PORT_NULL) {
                        // if server not available
                        if (sc_status == BOOTSTRAP_UNKNOWN_SERVICE) {
@@ -665,7 +856,7 @@ __SCNetworkConnectionSessionPort(SCNetworkConnectionPrivateRef connectionPrivate
        // clean up
 
 #ifdef HAVE_PPPCONTROLLER_ATTACHWITHAUDITSESSION
-       if (au_session != MACH_PORT_NULL){
+       if (au_session != MACH_PORT_NULL) {
                (void)mach_port_deallocate(mach_task_self(), au_session);
        }
 #endif // HAVE_PPPCONTROLLER_ATTACHWITHAUDITSESSION
@@ -731,17 +922,6 @@ __SCNetworkConnectionReconnectNotifications(SCNetworkConnectionRef connection)
        if (connectionPrivate->rlList != NULL) {
                rlList = CFArrayCreateCopy(NULL, connectionPrivate->rlList);
        }
-       if (connectionPrivate->dispatchQueue != NULL) {
-               // save dispatchQueue, release reference when we've queue'd blocks
-               // complete, allow re-scheduling
-               dispatchGroup = connectionPrivate->dispatchGroup;
-               connectionPrivate->dispatchGroup = NULL;
-               dispatchQueue = connectionPrivate->dispatchQueue;
-               connectionPrivate->dispatchQueue = NULL;
-
-               // and take an extra reference for rescheduling
-               dispatch_retain(dispatchQueue);
-       }
 
        // cancel [old] notifications
        if (connectionPrivate->rlList != NULL) {
@@ -758,6 +938,19 @@ __SCNetworkConnectionReconnectNotifications(SCNetworkConnectionRef connection)
                connectionPrivate->dispatchSource = NULL;
        }
 
+       /* Make sure dispatchSource is cancelled before removing group/queue */
+       if (connectionPrivate->dispatchQueue != NULL) {
+               // save dispatchQueue, release reference when we've queue'd blocks
+               // complete, allow re-scheduling
+               dispatchGroup = connectionPrivate->dispatchGroup;
+               connectionPrivate->dispatchGroup = NULL;
+               dispatchQueue = connectionPrivate->dispatchQueue;
+               connectionPrivate->dispatchQueue = NULL;
+
+               // and take an extra reference for rescheduling
+               dispatch_retain(dispatchQueue);
+       }
+
        connectionPrivate->scheduled = FALSE;
 
        pthread_mutex_unlock(&connectionPrivate->lock);
@@ -960,6 +1153,16 @@ SCNetworkConnectionCreateWithServiceID(CFAllocatorRef                     allocator,
 }
 
 
+SCNetworkConnectionRef
+SCNetworkConnectionCreate(CFAllocatorRef               allocator,
+                         SCNetworkConnectionCallBack   callout,
+                         SCNetworkConnectionContext    *context)
+{
+       SCNetworkConnectionPrivateRef   connectionPrivate = __SCNetworkConnectionCreatePrivate(allocator, NULL, callout, context);
+       return (SCNetworkConnectionRef)connectionPrivate;
+}
+
+
 CFStringRef
 SCNetworkConnectionCopyServiceID(SCNetworkConnectionRef connection)
 {
@@ -971,6 +1174,11 @@ SCNetworkConnectionCopyServiceID(SCNetworkConnectionRef connection)
                return NULL;
        }
 
+       if (connectionPrivate->service == NULL) {
+               _SCErrorSet(kSCStatusConnectionNoService);
+               return NULL;
+       }
+
        serviceID = SCNetworkServiceGetServiceID(connectionPrivate->service);
        return CFRetain(serviceID);
 }
@@ -990,7 +1198,7 @@ SCNetworkConnectionSetClientInfo(SCNetworkConnectionRef    connection,
                return FALSE;
        }
 
-       // save client bootstrap port
+       // save client audit session port
        if (connectionPrivate->client_audit_session != MACH_PORT_NULL) {
                mach_port_mod_refs(mach_task_self(),
                                   connectionPrivate->client_audit_session,
@@ -1015,6 +1223,72 @@ SCNetworkConnectionSetClientInfo(SCNetworkConnectionRef  connection,
 }
 
 
+Boolean
+SCNetworkConnectionSetClientAuditInfo(SCNetworkConnectionRef   connection,
+                                     audit_token_t             client_audit_token,
+                                     mach_port_t               audit_session,
+                                     mach_port_t               bootstrap_port,
+                                     pid_t                     client_pid,
+                                     const uuid_t              uuid,
+                                     const char                *bundle_id)
+{
+       const audit_token_t             null_audit              = KERNEL_AUDIT_TOKEN_VALUE;
+       SCNetworkConnectionPrivateRef   connectionPrivate       = (SCNetworkConnectionPrivateRef)connection;
+       gid_t                           gid                     = 0;
+       pid_t                           pid                     = 0;
+       uid_t                           uid                     = 0;
+
+       if (memcmp(&client_audit_token, &null_audit, sizeof(client_audit_token))) {
+#if    TARGET_OS_IPHONE
+           audit_token_to_au32(client_audit_token, NULL, &uid, &gid, NULL, NULL, &pid, NULL, NULL);
+#else  // TARGET_OS_IPHONE
+           uid = audit_token_to_euid(client_audit_token);
+           gid = audit_token_to_egid(client_audit_token);
+           pid = audit_token_to_pid(client_audit_token);
+#endif // TARGET_OS_IPHONE
+       } else {
+           pid = client_pid;
+       }
+
+       if (!SCNetworkConnectionSetClientInfo(connection, audit_session, uid, gid, pid)) {
+               return FALSE;
+       }
+
+       if (connectionPrivate->client_bootstrap_port != MACH_PORT_NULL) {
+               mach_port_mod_refs(mach_task_self(),
+                                  connectionPrivate->client_bootstrap_port,
+                                  MACH_PORT_RIGHT_SEND,
+                                  -1);
+               connectionPrivate->client_bootstrap_port = MACH_PORT_NULL;
+       }
+
+       connectionPrivate->client_bootstrap_port = bootstrap_port;
+       if (connectionPrivate->client_bootstrap_port != MACH_PORT_NULL) {
+               mach_port_mod_refs(mach_task_self(),
+                                  connectionPrivate->client_bootstrap_port,
+                                  MACH_PORT_RIGHT_SEND,
+                                  1);
+       }
+
+       memcpy(&connectionPrivate->client_audit_token, &client_audit_token, sizeof(connectionPrivate->client_audit_token));
+
+       if (uuid != NULL && !uuid_is_null(uuid)) {
+               uuid_copy(connectionPrivate->client_uuid, uuid);
+       }
+
+       if (connectionPrivate->client_bundle_id != NULL) {
+               CFRelease(connectionPrivate->client_bundle_id);
+               connectionPrivate->client_bundle_id = NULL;
+       }
+
+       if (bundle_id != NULL) {
+               connectionPrivate->client_bundle_id = CFStringCreateWithCString(kCFAllocatorDefault, bundle_id, kCFStringEncodingUTF8);
+       }
+
+       return TRUE;
+}
+
+
 CFDictionaryRef
 SCNetworkConnectionCopyStatistics(SCNetworkConnectionRef connection)
 {
@@ -1095,12 +1369,25 @@ SCNetworkConnectionGetStatus(SCNetworkConnectionRef connection)
        int                             sc_status               = kSCStatusFailed;
        mach_port_t                     session_port;
        kern_return_t                   status;
+       CFStringRef                     serviceID;
 
        if (!isA_SCNetworkConnection(connection)) {
                _SCErrorSet(kSCStatusInvalidArgument);
                return kSCNetworkConnectionInvalid;
        }
 
+       if (connectionPrivate->service == NULL) {
+               _SCErrorSet(kSCStatusConnectionNoService);
+               return kSCNetworkConnectionInvalid;
+       }
+
+       // skip retry and return immediately if we know no service is to be found.
+       serviceID = SCNetworkServiceGetServiceID(connectionPrivate->service);
+       if (CFStringGetLength(serviceID) == 0) {
+               _SCErrorSet(kSCStatusConnectionNoService);
+               return kSCNetworkConnectionInvalid;
+       }
+
        pthread_mutex_lock(&connectionPrivate->lock);
 
     retry :
@@ -1152,12 +1439,25 @@ SCNetworkConnectionCopyExtendedStatus(SCNetworkConnectionRef connection)
        int                             sc_status               = kSCStatusFailed;
        mach_port_t                     session_port;
        kern_return_t                   status;
+       CFStringRef                     serviceID;
 
        if (!isA_SCNetworkConnection(connection)) {
                _SCErrorSet(kSCStatusInvalidArgument);
                return NULL;
        }
 
+       if (connectionPrivate->service == NULL) {
+               _SCErrorSet(kSCStatusConnectionNoService);
+               return NULL;
+       }
+
+       // skip retry and return immediately if we know no service is to be found.
+       serviceID = SCNetworkServiceGetServiceID(connectionPrivate->service);
+       if (CFStringGetLength(serviceID) == 0) {
+               _SCErrorSet(kSCStatusConnectionNoService);
+               return NULL;
+       }
+
        pthread_mutex_lock(&connectionPrivate->lock);
 
     retry :
@@ -1209,6 +1509,14 @@ SCNetworkConnectionCopyExtendedStatus(SCNetworkConnectionRef connection)
 }
 
 
+static void
+_SCNetworkConnectionMergeDictionaries (const void *key, const void *value, void *context)
+{
+       /* Add value only if not present */
+       CFDictionaryAddValue((CFMutableDictionaryRef)context, (CFStringRef)key, (CFTypeRef)value);
+}
+
+
 Boolean
 SCNetworkConnectionStart(SCNetworkConnectionRef        connection,
                         CFDictionaryRef        userOptions,
@@ -1233,6 +1541,21 @@ SCNetworkConnectionStart(SCNetworkConnectionRef  connection,
                return FALSE;
        }
 
+       if (userOptions == NULL) {
+               userOptions = connectionPrivate->on_demand_user_options;
+       } else if (connectionPrivate->on_demand_user_options != NULL) {
+               CFDictionaryRef localUserOptions        = NULL;
+
+               localUserOptions = CFDictionaryCreateMutableCopy(NULL, 0, userOptions);
+               if (localUserOptions) {
+                       CFDictionaryApplyFunction(connectionPrivate->on_demand_user_options,
+                                                 _SCNetworkConnectionMergeDictionaries,
+                                                 (void *)localUserOptions);
+                       CFRelease(connectionPrivate->on_demand_user_options);
+                       userOptions = connectionPrivate->on_demand_user_options = localUserOptions;
+               }
+       }
+
        if (debug > 0) {
                CFMutableDictionaryRef  mdict = NULL;
 
@@ -1293,6 +1616,12 @@ SCNetworkConnectionStart(SCNetworkConnectionRef  connection,
 
        pthread_mutex_lock(&connectionPrivate->lock);
 
+       /* Clear out any cached flow divert token parameters */
+       if (connectionPrivate->flow_divert_token_params != NULL) {
+           CFRelease(connectionPrivate->flow_divert_token_params);
+           connectionPrivate->flow_divert_token_params = NULL;
+       }
+
     retry :
 
        session_port = __SCNetworkConnectionSessionPort(connectionPrivate);
@@ -1492,6 +1821,81 @@ SCNetworkConnectionResume(SCNetworkConnectionRef connection)
 }
 
 
+#if    !TARGET_IPHONE_SIMULATOR
+Boolean
+SCNetworkConnectionRefreshOnDemandState(SCNetworkConnectionRef connection)
+{
+       SCNetworkConnectionPrivateRef   connectionPrivate       = (SCNetworkConnectionPrivateRef)connection;
+       Boolean                         ok                      = FALSE;
+       uint32_t                        retry                   = 0;
+       int                             sc_status               = kSCStatusFailed;
+       mach_port_t                     server_port             = __SCNetworkConnectionGetCurrentServerPort();
+       kern_return_t                   status                  = KERN_SUCCESS;
+
+       if (!isA_SCNetworkConnection(connection)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return FALSE;
+       }
+
+       if (debug > 0) {
+               SCLog(TRUE, LOG_DEBUG, CFSTR("SCNetworkConnectionRefreshOnDemandState (0x%x)"), connectionPrivate);
+       }
+
+       pthread_mutex_lock(&connectionPrivate->lock);
+
+       while (TRUE) {
+               if (server_port == MACH_PORT_NULL) {
+                       server_port = __SCNetworkConnectionRefreshServerPort(server_port, &sc_status);
+                       if (server_port == MACH_PORT_NULL) {
+                               // if server not available
+                               if (sc_status == BOOTSTRAP_UNKNOWN_SERVICE) {
+                                       // wait up to 2.5 seconds for the [SCNetworkConnection] server
+                                       // to startup
+                                       if ((retry += 50) < 2500) {
+                                               usleep(50 * 1000);      // sleep 50ms between attempts
+                                               continue;
+                                       }
+                               }
+                               break;
+                       }
+               }
+
+               status = pppcontroller_ondemand_refresh_state(server_port, &sc_status);
+               if (status == KERN_SUCCESS)
+                       break;
+
+               if (status == MACH_SEND_INVALID_DEST) {
+                       // the server is not yet available
+                       SCLog(TRUE, LOG_ERR, CFSTR("SCNetworkConnectionRefreshOnDemandState (!dest) (0x%x)"), connectionPrivate);
+               } else if (status == MIG_SERVER_DIED) {
+                       // the server we were using is gone
+                       SCLog(TRUE, LOG_ERR, CFSTR("SCNetworkConnectionRefreshOnDemandState (!mig) (0x%x)"), connectionPrivate);
+               } else {
+                       // if we got an unexpected error, don't retry
+                       sc_status = status;
+                       break;
+               }
+       }
+
+       if (debug > 0) {
+               SCLog(TRUE, LOG_DEBUG, CFSTR("SCNetworkConnectionRefreshOnDemandState (0x%x), return: %d/%d"), connectionPrivate, status, sc_status);
+       }
+
+       if (sc_status != kSCStatusOK) {
+               _SCErrorSet(sc_status);
+               goto done;
+       }
+
+       ok = TRUE;
+
+    done :
+
+       pthread_mutex_unlock(&connectionPrivate->lock);
+       return ok;
+}
+#endif /* !TARGET_IPHONE_SIMULATOR */
+
+
 CFDictionaryRef
 SCNetworkConnectionCopyUserOptions(SCNetworkConnectionRef connection)
 {
@@ -1615,6 +2019,7 @@ __SCNetworkConnectionScheduleWithRunLoop(SCNetworkConnectionRef   connection,
        }
 
        if (queue != NULL) {
+               dispatch_group_t        group   = NULL;
                mach_port_t             mp;
                dispatch_source_t       source;
 
@@ -1644,7 +2049,8 @@ __SCNetworkConnectionScheduleWithRunLoop(SCNetworkConnectionRef   connection,
                // the group to empty and use the group's finalizer to release
                // our reference to the SCNetworkConnection.
                //
-               connectionPrivate->dispatchGroup = dispatch_group_create();
+               group = dispatch_group_create();
+               connectionPrivate->dispatchGroup = group;
                CFRetain(connection);
                dispatch_set_context(connectionPrivate->dispatchGroup, (void *)connection);
                dispatch_set_finalizer_f(connectionPrivate->dispatchGroup, (dispatch_function_t)CFRelease);
@@ -1674,7 +2080,8 @@ __SCNetworkConnectionScheduleWithRunLoop(SCNetworkConnectionRef   connection,
 
                        CFRetain(connection);
                        notify_port = dispatch_get_context(source);
-                       dispatch_group_async(connectionPrivate->dispatchGroup, connectionPrivate->dispatchQueue, ^{
+
+                       dispatch_group_async(group, queue, ^{
                                __SCNetworkConnectionCallBack(notify_port,
                                                              (void *)&notify_msg.msg,
                                                              sizeof(notify_msg),
@@ -1874,47 +2281,453 @@ SCNetworkConnectionSetDispatchQueue(SCNetworkConnectionRef     connection,
 }
 
 
-#pragma mark -
-#pragma mark User level "dial" API
-
-
-#define k_NetworkConnect_Notification  "com.apple.networkConnect"
-#define k_NetworkConnect_Pref_File     CFSTR("com.apple.networkConnect")
-#define k_InterentConnect_Pref_File    CFSTR("com.apple.internetconnect")
+/* Requires having called SCNetworkConnectionSelectServiceWithOptions previously */
+Boolean
+SCNetworkConnectionIsOnDemandSuspended(SCNetworkConnectionRef connection)
+{
+       SCNetworkConnectionPrivateRef   connectionPrivate       = (SCNetworkConnectionPrivateRef)connection;
 
-#define k_Dial_Default_Key             CFSTR("ConnectByDefault") // needs to go into SC
-#define k_Last_Service_Id_Key          CFSTR("ServiceID")
-#define k_Unique_Id_Key                        CFSTR("UniqueIdentifier")
+       if (!isA_SCNetworkConnection(connection)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return FALSE;
+       }
 
+       if (connectionPrivate->on_demand_info != NULL) {
+               uint32_t        isSuspended     = 0;
+               CFNumberRef     num             = NULL;
 
-/* Private Prototypes */
-static Boolean SCNetworkConnectionPrivateCopyDefaultServiceIDForDial   (SCDynamicStoreRef session, CFStringRef *serviceID);
-static Boolean SCNetworkConnectionPrivateGetPPPServiceFromDynamicStore (SCDynamicStoreRef session, CFStringRef *serviceID);
-static Boolean SCNetworkConnectionPrivateCopyDefaultUserOptionsFromArray(CFArrayRef userOptionsArray, CFDictionaryRef *userOptions);
-static Boolean SCNetworkConnectionPrivateIsPPPService                  (SCDynamicStoreRef session, CFStringRef serviceID, CFStringRef subType1, CFStringRef subType2);
-static void addPasswordFromKeychain                                    (SCDynamicStoreRef session, CFStringRef serviceID, CFDictionaryRef *userOptions);
-static CFStringRef copyPasswordFromKeychain                            (CFStringRef uniqueID);
+               num = CFDictionaryGetValue(connectionPrivate->on_demand_info, kSCPropNetVPNOnDemandSuspended);
+               if (isA_CFNumber(num) &&
+                   CFNumberGetValue(num, kCFNumberSInt32Type, &isSuspended) &&
+                   (isSuspended != 0)) {
+                       return TRUE;
+               }
+       }
 
-static int             notify_userprefs_token  = -1;
+       _SCErrorSet(kSCStatusOK);
+       return FALSE;
+}
 
-static CFDictionaryRef onDemand_configuration  = NULL;
-static pthread_mutex_t onDemand_notify_lock    = PTHREAD_MUTEX_INITIALIZER;
-static int             onDemand_notify_token   = -1;
+static void
+SCNetworkConnectionTriggerOnDemandCallback (SCNetworkConnectionRef          connection,
+                                           SCNetworkConnectionStatus       status,
+                                           void                            *info)
+{
+       dispatch_group_t group = (dispatch_group_t)info;
+       if (status != kSCNetworkConnectionConnecting) {
+               dispatch_group_leave(group);
+       }
+}
 
-/*
- *     return TRUE if domain1 ends with domain2, and will check for trailing "."
- */
 Boolean
-_SC_domainEndsWithDomain(CFStringRef compare_domain, CFStringRef match_domain)
+SCNetworkConnectionTriggerOnDemandIfNeeded     (CFStringRef                    hostName,
+                                                Boolean                        afterDNSFail,
+                                                int                            timeout,
+                                                int                            trafficClass)
 {
-       CFRange         range;
-       Boolean         ret             = FALSE;
-       CFStringRef     s1              = NULL;
-       Boolean         s1_created      = FALSE;
+       SCNetworkConnectionRef          connection = NULL;
+       dispatch_group_t                group = NULL;
+       CFMutableDictionaryRef          options_dict = NULL;
+       Boolean                         connectedIfNeeded = FALSE;
+
+       /* Require hostName, require non-root user */
+       if (hostName == NULL || geteuid() == 0) {
+               goto done;
+       }
+
+       group = dispatch_group_create();
+       if (group == NULL) {
+               goto done;
+       }
+
+       SCNetworkConnectionContext context = { 0, (void*)group, NULL, NULL, NULL };
+       connection = SCNetworkConnectionCreate(kCFAllocatorDefault, SCNetworkConnectionTriggerOnDemandCallback, &context);
+       if (connection == NULL) {
+               goto done;
+       }
+
+       options_dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+       if (options_dict == NULL) {
+               goto done;
+       }
+
+       CFDictionaryAddValue(options_dict, kSCNetworkConnectionSelectionOptionOnDemandHostName, hostName);
+       CFDictionaryAddValue(options_dict, kSCNetworkConnectionSelectionOptionOnDemandRetry, (afterDNSFail ? kCFBooleanTrue : kCFBooleanFalse));
+
+       if (trafficClass) {
+               CFNumberRef trafficClassRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &trafficClass);
+               if (trafficClassRef) {
+                       CFDictionaryAddValue(options_dict, kSCNetworkConnectionSelectionOptionOnDemandTrafficClass, trafficClassRef);
+                       CFRelease(trafficClassRef);
+               }
+       }
+
+       if (SCNetworkConnectionSelectServiceWithOptions(connection, options_dict)) {
+               SCNetworkConnectionStatus status = SCNetworkConnectionGetStatus(connection);
+
+               if (status == kSCNetworkConnectionConnected) {
+                       /* If already connected, done */
+                       connectedIfNeeded = TRUE;
+               } else if (status == kSCNetworkConnectionDisconnected || status == kSCNetworkConnectionConnecting) {
+                       dispatch_queue_t callback_queue = dispatch_queue_create("SCNetworkConnectionTrigger queue", NULL);
+                       if (callback_queue) {
+                               SCNetworkConnectionSetDispatchQueue(connection, callback_queue);
+
+                               dispatch_group_enter(group);
+
+                               /* If the connection is already connecting, we don't need to start.
+                                If disconnected, do call start. */
+                               if (status == kSCNetworkConnectionDisconnected) {
+                                       SCNetworkConnectionStart(connection, NULL, TRUE);
+                               }
+
+                               dispatch_group_wait(group, (timeout == 0) ? DISPATCH_TIME_FOREVER : dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * timeout));
+
+                               SCNetworkConnectionSetDispatchQueue(connection, NULL);
+
+                               status = SCNetworkConnectionGetStatus(connection);
+                               if (status == kSCNetworkConnectionConnected) {
+                                       connectedIfNeeded = TRUE;
+                               }
+
+                               dispatch_release(callback_queue);
+                       }
+               }
+       } else {
+               /* Not needed, so we can return true */
+               connectedIfNeeded = TRUE;
+       }
+
+done:
+       if (options_dict) {
+               CFRelease(options_dict);
+       }
+
+       if (connection) {
+               CFRelease(connection);
+       }
+
+       if (group) {
+               dispatch_release(group);
+       }
+
+       return connectedIfNeeded;
+}
+
+
+Boolean
+SCNetworkConnectionCopyOnDemandInfo(SCNetworkConnectionRef     connection,
+                                   CFStringRef                 *onDemandRemoteAddress,
+                                   SCNetworkConnectionStatus   *onDemandConnectionStatus)
+{
+       SCNetworkConnectionPrivateRef   connectionPrivate       = (SCNetworkConnectionPrivateRef)connection;
+
+       if (!isA_SCNetworkConnection(connection)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return FALSE;
+       }
+
+       if (connectionPrivate->service == NULL) {
+               _SCErrorSet(kSCStatusConnectionNoService);
+               return FALSE;
+       }
+
+       if (onDemandRemoteAddress != NULL) {
+               *onDemandRemoteAddress = NULL;
+       }
+
+       if (onDemandConnectionStatus != NULL) {
+               *onDemandConnectionStatus = kSCNetworkConnectionInvalid;
+       }
+
+       if (connectionPrivate->on_demand_info != NULL) {
+               if (onDemandRemoteAddress != NULL) {
+                       CFStringRef address =
+                           CFDictionaryGetValue(connectionPrivate->on_demand_info, kSCNetworkConnectionOnDemandRemoteAddress);
+                       if (isA_CFString(address)) {
+                               *onDemandRemoteAddress = address;
+                               CFRetain(*onDemandRemoteAddress);
+                       }
+               }
+
+               if (onDemandConnectionStatus != NULL) {
+                       int num;
+                       CFNumberRef status_num =
+                           CFDictionaryGetValue(connectionPrivate->on_demand_info, kSCNetworkConnectionOnDemandStatus);
+                       if (isA_CFNumber(status_num) && CFNumberGetValue(status_num, kCFNumberIntType, &num)) {
+                               *onDemandConnectionStatus = num;
+                       }
+               }
+       }
+
+       return connectionPrivate->on_demand;
+}
+
+
+Boolean
+SCNetworkConnectionGetReachabilityInfo(SCNetworkConnectionRef          connection,
+                                      SCNetworkReachabilityFlags       *reach_flags,
+                                      unsigned int                     *reach_if_index)
+{
+       SCNetworkConnectionPrivateRef   connectionPrivate       = (SCNetworkConnectionPrivateRef)connection;
+
+       if (!isA_SCNetworkConnection(connection)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return FALSE;
+       }
+
+       if (connectionPrivate->service == NULL) {
+               _SCErrorSet(kSCStatusConnectionNoService);
+               return FALSE;
+       }
+
+       if (reach_flags != NULL) {
+               *reach_flags = 0;
+       }
+
+       if (reach_if_index != NULL) {
+               *reach_if_index = 0;
+       }
+
+       if (connectionPrivate->on_demand_info != NULL) {
+               if (reach_flags != NULL) {
+                       int num;
+                       CFNumberRef flags_num =
+                           CFDictionaryGetValue(connectionPrivate->on_demand_info, kSCNetworkConnectionOnDemandReachFlags);
+                       if (isA_CFNumber(flags_num) && CFNumberGetValue(flags_num, kCFNumberIntType, &num)) {
+                               *reach_flags = num;
+                       }
+               }
+
+               if (reach_if_index != NULL) {
+                       int num;
+                       CFNumberRef if_index_num =
+                           CFDictionaryGetValue(connectionPrivate->on_demand_info, kSCNetworkConnectionOnDemandReachInterfaceIndex);
+                       if (isA_CFNumber(if_index_num) && CFNumberGetValue(if_index_num, kCFNumberIntType, &num)) {
+                               *reach_if_index = num;
+                       }
+               }
+       }
+
+       return TRUE;
+}
+
+
+SCNetworkConnectionType
+SCNetworkConnectionGetType(SCNetworkConnectionRef connection)
+{
+       SCNetworkConnectionPrivateRef   connectionPrivate       = (SCNetworkConnectionPrivateRef)connection;
+
+       if (!isA_SCNetworkConnection(connection)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return kSCNetworkConnectionTypeUnknown;
+       }
+
+       if (connectionPrivate->service == NULL) {
+               _SCErrorSet(kSCStatusConnectionNoService);
+               return kSCNetworkConnectionTypeUnknown;
+       }
+
+       _SCErrorSet(kSCStatusOK);
+
+       return connectionPrivate->type;
+}
+
+
+static Boolean
+validate_flow_properties(CFDictionaryRef flowProperties)
+{
+       CFStringRef                     host_name_str;
+       CFDataRef                       host_address_data;
+       CFNumberRef                     host_port_num;
+
+       if (!isA_CFDictionary(flowProperties)) {
+               return FALSE;
+       }
+
+       /* Validate the host name if one was given */
+       host_name_str = CFDictionaryGetValue(flowProperties, kSCNetworkConnectionFlowPropertyHostName);
+       if (host_name_str != NULL && (!isA_CFString(host_name_str) || CFStringGetLength(host_name_str) == 0)) {
+               return FALSE;
+       }
+
+       /* Validate the address if one was given */
+       host_address_data = CFDictionaryGetValue(flowProperties, kSCNetworkConnectionFlowPropertyHostAddress);
+       if (host_address_data != NULL) {
+               struct sockaddr *sock_addr;
+
+               if (!isA_CFData(host_address_data) || CFDataGetLength(host_address_data) < sizeof(struct sockaddr)) {
+                       return FALSE;
+               }
+
+               sock_addr = (struct sockaddr *)CFDataGetBytePtr(host_address_data);
+               if (CFDataGetLength(host_address_data) < sock_addr->sa_len) {
+                       return FALSE;
+               }
+
+               if (sock_addr->sa_family == AF_INET) {
+                       if (sock_addr->sa_len >= sizeof(struct sockaddr_in)) {
+                               struct sockaddr_in *sa_in = (struct sockaddr_in *)(void *)sock_addr;
+                               in_addr_t any = { INADDR_ANY };
+                               if (memcmp(&sa_in->sin_addr, &any, sizeof(any)) == 0) {
+                                       return FALSE;
+                               }
+                       } else {
+                               return FALSE;
+                       }
+               } else if (sock_addr->sa_family == AF_INET6) {
+                       if (sock_addr->sa_len >= sizeof(struct sockaddr_in6)) {
+                               struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)(void *)sock_addr;
+                               struct in6_addr any = IN6ADDR_ANY_INIT;
+                               if (memcmp(&sa_in6->sin6_addr, &any, sizeof(any)) == 0) {
+                                       return FALSE;
+                               }
+                       }
+               }
+       }
+
+       /* We must have either a host name or an address */
+       if (host_name_str == NULL && host_address_data == NULL) {
+               return FALSE;
+       }
+
+       /* Validate the port */
+       host_port_num = CFDictionaryGetValue(flowProperties, kSCNetworkConnectionFlowPropertyHostPort);
+       if (host_port_num != NULL) {
+               int num;
+               if (!isA_CFNumber(host_port_num) || !CFNumberGetValue(host_port_num, kCFNumberIntType, &num)) {
+                       return FALSE;
+               }
+
+               if (num == 0) {
+                       return FALSE;
+               }
+       } else {
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+
+CFDataRef
+SCNetworkConnectionCopyFlowDivertToken(SCNetworkConnectionRef  connection,
+                                      CFDictionaryRef          flowProperties)
+{
+       CFDictionaryRef                 app_properties          = NULL;
+       SCNetworkConnectionPrivateRef   connectionPrivate       = (SCNetworkConnectionPrivateRef)connection;
+       CFDataRef                       token                   = NULL;
+
+       if (!isA_SCNetworkConnection(connection)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               goto done;
+       }
+
+       if (connectionPrivate->service == NULL) {
+               _SCErrorSet(kSCStatusConnectionNoService);
+               goto done;
+       }
+
+       if (connectionPrivate->type != kSCNetworkConnectionTypeAppLayerVPN) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               goto done;
+       }
+
+       if (!validate_flow_properties(flowProperties)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               goto done;
+       }
+
+       app_properties = VPNAppLayerCopyCachedAppProperties(connectionPrivate->client_audit_token,
+                                                           connectionPrivate->client_pid,
+                                                           connectionPrivate->client_uuid,
+                                                           connectionPrivate->client_bundle_id);
+       if (app_properties == NULL) {
+               SCLog(TRUE, LOG_ERR, CFSTR("SCNetworkConnectionCopyFlowDivertToken: no cached app properties available"));
+               _SCErrorSet(kSCStatusFailed);
+               goto done;
+       }
+
+       token = VPNAppLayerCreateFlowDivertToken(connection, app_properties, flowProperties);
+
+done:
+       if (app_properties != NULL) {
+               CFRelease(app_properties);
+       }
+
+       return token;
+}
+
+
+int
+SCNetworkConnectionGetServiceIdentifier                (SCNetworkConnectionRef         connection)
+{
+       SCNetworkConnectionPrivateRef   connectionPrivate       = (SCNetworkConnectionPrivateRef)connection;
+       int                             service_identifier      = -1;
+
+       if (connectionPrivate->service != NULL) {
+               service_identifier = 0;
+               if (connectionPrivate->on_demand_info != NULL) {
+                       CFNumberRef id_num = CFDictionaryGetValue(connectionPrivate->on_demand_info, kSCPropNetDNSServiceIdentifier);
+
+                       if (isA_CFNumber(id_num)) {
+                               CFNumberGetValue(id_num, kCFNumberIntType, &service_identifier);
+                       }
+               }
+       }
+
+       return service_identifier;
+}
+
+
+#pragma mark -
+#pragma mark User level "dial" API
+
+
+#define k_NetworkConnect_Notification  "com.apple.networkConnect"
+#define k_NetworkConnect_Pref_File     CFSTR("com.apple.networkConnect")
+#define k_InterentConnect_Pref_File    CFSTR("com.apple.internetconnect")
+
+#define k_Dial_Default_Key             CFSTR("ConnectByDefault") // needs to go into SC
+#define k_Last_Service_Id_Key          CFSTR("ServiceID")
+#define k_Unique_Id_Key                        CFSTR("UniqueIdentifier")
+
+
+/* Private Prototypes */
+static Boolean SCNetworkConnectionPrivateCopyDefaultServiceIDForDial   (CFStringRef *serviceID);
+static Boolean SCNetworkConnectionPrivateGetPPPServiceFromDynamicStore (CFStringRef *serviceID);
+static Boolean SCNetworkConnectionPrivateCopyDefaultUserOptionsFromArray(CFArrayRef userOptionsArray, CFDictionaryRef *userOptions);
+static Boolean SCNetworkConnectionPrivateIsPPPService                  (CFStringRef serviceID, CFStringRef subType1, CFStringRef subType2);
+static void addPasswordFromKeychain                                    (CFStringRef serviceID, CFDictionaryRef *userOptions);
+static CFStringRef copyPasswordFromKeychain                            (CFStringRef uniqueID);
+
+static int             notify_userprefs_token  = -1;
+
+static CFDictionaryRef onDemand_configuration  = NULL;
+static Boolean         onDemand_force_refresh  = FALSE;
+static pthread_mutex_t onDemand_notify_lock    = PTHREAD_MUTEX_INITIALIZER;
+static int             onDemand_notify_token   = -1;
+
+
+/*
+ *     return TRUE if domain1 ends with domain2, and will check for trailing "."
+ */
+#define WILD_CARD_MATCH_STR CFSTR("*")
+Boolean
+_SC_domainEndsWithDomain(CFStringRef compare_domain, CFStringRef match_domain)
+{
+       CFRange         range;
+       Boolean         ret             = FALSE;
+       CFStringRef     s1              = NULL;
+       Boolean         s1_created      = FALSE;
        CFStringRef     s2              = NULL;
        Boolean         s2_created      = FALSE;
        CFStringRef     s3              = NULL;
 
+       if (CFEqual(match_domain, WILD_CARD_MATCH_STR)) {
+               return TRUE;
+       }
+
        if (CFStringHasSuffix(compare_domain, CFSTR("."))) {
                range.location = 0;
                range.length = CFStringGetLength(compare_domain) - 1;
@@ -1964,22 +2777,13 @@ _SC_domainEndsWithDomain(CFStringRef compare_domain, CFStringRef match_domain)
 
 /* VPN On Demand */
 
-Boolean
-__SCNetworkConnectionCopyOnDemandInfoWithName(SCDynamicStoreRef                *storeP,
-                                             CFStringRef               hostName,
-                                             Boolean                   onDemandRetry,
-                                             CFStringRef               *connectionServiceID,
-                                             SCNetworkConnectionStatus *connectionStatus,
-                                             CFStringRef               *vpnRemoteAddress)      /*  CFDictionaryRef *info */
+static CFDictionaryRef
+__SCNetworkConnectionCopyOnDemandConfiguration(void)
 {
        int                     changed         = 1;
-       CFDictionaryRef         configuration;
-       Boolean                 ok              = FALSE;
        int                     status;
-       SCDynamicStoreRef       store           = *storeP;
-       CFArrayRef              triggers;
        uint64_t                triggersCount   = 0;
-       int                     triggersIndex;
+       CFDictionaryRef         configuration;
 
        pthread_mutex_lock(&onDemand_notify_lock);
        if (onDemand_notify_token == -1) {
@@ -1989,6 +2793,7 @@ __SCNetworkConnectionCopyOnDemandInfoWithName(SCDynamicStoreRef           *storeP,
                        onDemand_notify_token = -1;
                }
        }
+
        if (onDemand_notify_token != -1) {
                status = notify_check(onDemand_notify_token, &changed);
                if (status != NOTIFY_STATUS_OK) {
@@ -2007,7 +2812,7 @@ __SCNetworkConnectionCopyOnDemandInfoWithName(SCDynamicStoreRef           *storeP,
                }
        }
 
-       if (changed) {
+       if (changed || onDemand_force_refresh) {
                CFStringRef     key;
 
                if (_sc_debug || (debug > 0)) {
@@ -2021,179 +2826,765 @@ __SCNetworkConnectionCopyOnDemandInfoWithName(SCDynamicStoreRef               *storeP,
                        onDemand_configuration = NULL;
                }
 
-               if (triggersCount > 0) {
-                       if (store == NULL) {
-                               store = SCDynamicStoreCreate(NULL, CFSTR("__SCNetworkConnectionCopyOnDemandInfoWithName"), NULL, NULL);
-                               if (store == NULL) {
-                                       SCLog(TRUE, LOG_ERR, CFSTR("__SCNetworkConnectionCopyOnDemandInfoWithName SCDynamicStoreCreate() failed"));
-
-                                       // force retry on next check
-                                       if (onDemand_notify_token != -1) {
-                                               (void)notify_cancel(onDemand_notify_token);
-                                               onDemand_notify_token = -1;
-                                       }
-                                       pthread_mutex_unlock(&onDemand_notify_lock);
-                                       return FALSE;
-                               }
-                               *storeP = store;
-                       }
-
+               if ((triggersCount > 0) || onDemand_force_refresh) {
                        key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetOnDemand);
-                       onDemand_configuration = SCDynamicStoreCopyValue(store, key);
+                       onDemand_configuration = SCDynamicStoreCopyValue(NULL, key);
                        CFRelease(key);
                        if ((onDemand_configuration != NULL) && !isA_CFDictionary(onDemand_configuration)) {
                                CFRelease(onDemand_configuration);
                                onDemand_configuration = NULL;
                        }
                }
+
+               onDemand_force_refresh = FALSE;
        }
 
        configuration = (onDemand_configuration != NULL) ? CFRetain(onDemand_configuration) : NULL;
        pthread_mutex_unlock(&onDemand_notify_lock);
 
-       if (configuration == NULL) {
-               // if no "OnDemand" configurations
-               return FALSE;
-       }
+       return configuration;
+}
 
-       triggers = CFDictionaryGetValue(configuration, kSCNetworkConnectionOnDemandTriggers);
-       triggersCount = isA_CFArray(triggers) ? CFArrayGetCount(triggers) : 0;
-       for (triggersIndex = 0; triggersIndex < triggersCount; triggersIndex++) {
-               CFArrayRef      domains;
-               int             domainsCount;
-               int             domainsIndex;
-               CFStringRef     key;
-               CFDictionaryRef trigger;
 
-               trigger = CFArrayGetValueAtIndex(triggers, triggersIndex);
-               if (!isA_CFDictionary(trigger)) {
-                       // if not a valid "OnDemand" configuration
-                       continue;
-               }
+__private_extern__
+void
+__SCNetworkConnectionForceOnDemandConfigurationRefresh(void)
+{
+       pthread_mutex_lock(&onDemand_notify_lock);
+       onDemand_force_refresh = TRUE;
+       pthread_mutex_unlock(&onDemand_notify_lock);
 
-               /*
-                * If we haven't tried a resulution yet, we only want to check for a name
-                * match for domains that require to always connect.
-                */
-               key = onDemandRetry ? kSCNetworkConnectionOnDemandMatchDomainsOnRetry
-                                   : kSCNetworkConnectionOnDemandMatchDomainsAlways;
-               domains = CFDictionaryGetValue(trigger, key);
-               domainsCount = isA_CFArray(domains) ? CFArrayGetCount(domains) : 0;
-               for (domainsIndex = 0; domainsIndex < domainsCount; domainsIndex++) {
+       return;
+}
+
+
+static Boolean
+__SCNetworkConnectionShouldNeverMatch(CFDictionaryRef trigger, CFStringRef hostName, pid_t client_pid)
+{
+       CFArrayRef      exceptedProcesses;
+       int             exceptedProcessesCount;
+       int             exceptedProcessesIndex;
+       CFArrayRef      exceptions;
+       int             exceptionsCount;
+       int             exceptionsIndex;
+
+       // we have a matching domain, check against exception list
+       exceptions = CFDictionaryGetValue(trigger, kSCNetworkConnectionOnDemandMatchDomainsNever);
+       exceptionsCount = isA_CFArray(exceptions) ? CFArrayGetCount(exceptions) : 0;
+       for (exceptionsIndex = 0; exceptionsIndex < exceptionsCount; exceptionsIndex++) {
+               CFStringRef     exception;
+
+               exception = CFArrayGetValueAtIndex(exceptions, exceptionsIndex);
+               if (isA_CFString(exception) && _SC_domainEndsWithDomain(hostName, exception)) {
+                       // found matching exception
+                       if (_sc_debug || (debug > 0)) {
+                               SCLog(TRUE, LOG_INFO, CFSTR("OnDemand match exception"));
+                       }
+                       return TRUE;
+               }
+       }
+
+       if (client_pid != 0) {
+               exceptedProcesses = CFDictionaryGetValue(trigger, kSCNetworkConnectionOnDemandPluginPIDs);
+               exceptedProcessesCount = isA_CFArray(exceptedProcesses) ? CFArrayGetCount(exceptedProcesses) : 0;
+               for (exceptedProcessesIndex = 0; exceptedProcessesIndex < exceptedProcessesCount; exceptedProcessesIndex++) {
+                       int             pid;
+                       CFNumberRef     pidRef;
+
+                       pidRef = CFArrayGetValueAtIndex(exceptedProcesses, exceptedProcessesIndex);
+                       if (isA_CFNumber(pidRef) && CFNumberGetValue(pidRef, kCFNumberIntType, &pid)) {
+                               if (pid == client_pid) {
+                                       return TRUE;
+                               }
+                       }
+               }
+       }
+
+       return FALSE;
+}
+
+static CFStringRef
+__SCNetworkConnectionDomainGetMatchWithParameters(CFStringRef action, CFPropertyListRef actionParameters, CFStringRef hostName, CFStringRef *probeString)
+{
+       CFArrayRef      actionArray = NULL;
+       CFIndex         actionArraySize = 0;
+       CFIndex         i;
+       CFStringRef     matchDomain     = NULL;
+
+       /* For now, only support EvaluateConnection, which takes a CFArray */
+       if (!CFEqual(action, kSCValNetVPNOnDemandRuleActionEvaluateConnection) || !isA_CFArray(actionParameters)) {
+               return NULL;
+       }
+
+       actionArray = (CFArrayRef)actionParameters;
+       actionArraySize = CFArrayGetCount(actionArray);
+
+       /* Process domain rules, with actions of ConnectIfNeeded and NeverConnect */
+       for (i = 0; i < actionArraySize; i++) {
+               CFStringRef     domainAction = NULL;
+               CFDictionaryRef domainRule = CFArrayGetValueAtIndex(actionArray, i);
+               CFArrayRef      domains = NULL;
+               CFIndex         domainsCount = 0;
+               CFIndex         domainsIndex;
+
+               if (!isA_CFDictionary(domainRule)) {
+                       continue;
+               }
+
+               domains = CFDictionaryGetValue(domainRule, kSCPropNetVPNOnDemandRuleActionParametersDomains);
+               if (!isA_CFArray(domains)) {
+                       continue;
+               }
+
+               domainsCount = CFArrayGetCount(domains);
+               for (domainsIndex = 0; domainsIndex < domainsCount; domainsIndex++) {
                        CFStringRef     domain;
+                       domain = CFArrayGetValueAtIndex(domains, domainsIndex);
+                       if (isA_CFString(domain) && _SC_domainEndsWithDomain(hostName, domain)) {
+                               matchDomain = domain;
+                               break;
+                       }
+               }
+
+               if (matchDomain) {
+                       domainAction = CFDictionaryGetValue(domainRule, kSCPropNetVPNOnDemandRuleActionParametersDomainAction);
+                       if (isA_CFString(domainAction) && CFEqual(domainAction, kSCValNetVPNOnDemandRuleActionParametersDomainActionNeverConnect)) {
+                               return NULL;
+                       } else {
+                               /* If we found a match, save the optional probe string as well */
+                               if (probeString) {
+                                       *probeString = CFDictionaryGetValue(domainRule, kSCPropNetVPNOnDemandRuleActionParametersRequiredURLStringProbe);
+                               }
+                               break;
+                       }
+               }
+       }
+
+       return matchDomain;
+}
+
+static CFStringRef
+__SCNetworkConnectionDomainGetMatch(CFDictionaryRef trigger, CFStringRef hostName, Boolean onDemandRetry)
+{
+       CFArrayRef      domains;
+       int             domainsCount;
+       int             domainsIndex;
+       CFStringRef     key;
+       CFStringRef     match_domain    = NULL;
+
+       /* Old configuration: always, never, on retry lists */
+       key = onDemandRetry ? kSCNetworkConnectionOnDemandMatchDomainsOnRetry : kSCNetworkConnectionOnDemandMatchDomainsAlways;
+
+       domains = CFDictionaryGetValue(trigger, key);
+       domainsCount = isA_CFArray(domains) ? CFArrayGetCount(domains) : 0;
+       for (domainsIndex = 0; domainsIndex < domainsCount; domainsIndex++) {
+               CFStringRef     domain;
+
+               domain = CFArrayGetValueAtIndex(domains, domainsIndex);
+               if (isA_CFString(domain) && _SC_domainEndsWithDomain(hostName, domain)) {
+                       match_domain = domain;
+                       break;
+               }
+       }
+
+       return match_domain;
+}
+
+
+static Boolean
+__SCNetworkConnectionShouldAlwaysConnect(CFDictionaryRef trigger)
+{
+       CFStringRef action = CFDictionaryGetValue(trigger, kSCPropNetVPNOnDemandRuleAction);
+       return (isA_CFString(action) && CFEqual(action, kSCValNetVPNOnDemandRuleActionConnect));
+}
+
+
+static Boolean
+__SCNetworkConnectionShouldIgnoreTrigger(CFDictionaryRef trigger)
+{
+       CFStringRef     action          = CFDictionaryGetValue(trigger, kSCPropNetVPNOnDemandRuleAction);
+       int             flags;
+       CFNumberRef     reachFlags;
+
+       if (isA_CFString(action) &&
+           (CFEqual(action, kSCValNetVPNOnDemandRuleActionIgnore) ||
+            CFEqual(action, kSCValNetVPNOnDemandRuleActionDisconnect))) {
+                   return TRUE;
+       }
+
+       /* If the VPN server is not reachable immediately, ignore this trigger */
+       reachFlags = CFDictionaryGetValue(trigger, kSCNetworkConnectionOnDemandReachFlags);
+       if (isA_CFNumber(reachFlags) && CFNumberGetValue(reachFlags, kCFNumberIntType, &flags)) {
+               if (!(flags & kSCNetworkReachabilityFlagsReachable) || (flags & kSCNetworkReachabilityFlagsConnectionRequired)) {
+                       return TRUE;
+               }
+       }
+
+       return FALSE;
+}
+
+
+static CFDictionaryRef
+__SCNetworkConnectionCopyMatchingTriggerWithName(CFDictionaryRef       configuration,
+                                                CFStringRef            hostName,
+                                                pid_t                  client_pid,
+                                                Boolean                onDemandRetry,
+                                                CFDictionaryRef        *match_info,
+                                                Boolean                *triggerNow,
+                                                CFStringRef            *probe_string)
+{
+       CFDictionaryRef result          = NULL;
+       int             sc_status       = kSCStatusOK;
+       CFArrayRef      triggers;
+       uint64_t        triggersCount   = 0;
+       int             triggersIndex;
+       Boolean         usedOnDemandRetry = FALSE;
+
+       if (triggerNow != NULL) {
+               *triggerNow = FALSE;
+       }
+
+       if (match_info != NULL) {
+               *match_info = NULL;
+       }
+
+       triggers = CFDictionaryGetValue(configuration, kSCNetworkConnectionOnDemandTriggers);
+       triggersCount = isA_CFArray(triggers) ? CFArrayGetCount(triggers) : 0;
+       for (triggersIndex = 0; triggersIndex < triggersCount; triggersIndex++) {
+               CFStringRef     matched_domain  = NULL;
+               CFStringRef     matched_probe_string = NULL;
+               CFDictionaryRef trigger;
+               Boolean         trigger_matched = FALSE;
+
+               usedOnDemandRetry = FALSE;
+
+               trigger = CFArrayGetValueAtIndex(triggers, triggersIndex);
+               if (!isA_CFDictionary(trigger)) {
+                       // if not a valid "OnDemand" configuration
+                       continue;
+               }
+
+               if (__SCNetworkConnectionShouldAlwaysConnect(trigger)) {
+                       /* If the trigger action is 'Connect', always match this trigger */
+                       /* First check the never match list */
+                       if (__SCNetworkConnectionShouldNeverMatch(trigger, hostName, client_pid)) {
+                               continue;
+                       }
+                       trigger_matched = TRUE;
+               } else if (__SCNetworkConnectionShouldIgnoreTrigger(trigger)) {
+                       /* If the trigger action is 'Ignore' or 'Disconnect', skip this trigger */
+                       sc_status = kSCStatusConnectionIgnore;
+                       continue;
+               } else {
+                       CFStringRef action = CFDictionaryGetValue(trigger, kSCPropNetVPNOnDemandRuleAction);
+                       CFArrayRef actionParameters = CFDictionaryGetValue(trigger, kSCPropNetVPNOnDemandRuleActionParameters);
+                       if (action && actionParameters) {
+                               matched_domain = __SCNetworkConnectionDomainGetMatchWithParameters(action, actionParameters, hostName, &matched_probe_string);
+                               usedOnDemandRetry = TRUE;
+                       } else {
+                               if (onDemandRetry) {
+                                       matched_domain = __SCNetworkConnectionDomainGetMatch(trigger, hostName, TRUE);
+                                       usedOnDemandRetry = TRUE;
+                               } else {
+                                       matched_domain = __SCNetworkConnectionDomainGetMatch(trigger, hostName, FALSE);
+                                       if (matched_domain == NULL && result == NULL) {
+                                               /* Check the retry list if Always failed */
+                                               matched_domain = __SCNetworkConnectionDomainGetMatch(trigger, hostName, TRUE);
+                                               usedOnDemandRetry = TRUE;
+                                       }
+                               }
+                       }
+
+                       if (matched_domain) {
+                               if (__SCNetworkConnectionShouldNeverMatch(trigger, hostName, client_pid)) {
+                                       matched_domain = NULL;
+                                       continue;
+                               } else {
+                                       trigger_matched = TRUE;
+                               }
+                       }
+               }
+
+               if (trigger_matched) {
+                       // if we have a matching domain and there were no exceptions
+                       // then we pass back the OnDemand info
+                       if (match_info != NULL) {
+                               CFMutableDictionaryRef  minfo;
+                               SCNetworkConnectionType type    = kSCNetworkConnectionTypeIPLayerVPN;
+                               CFNumberRef             type_num;
+
+                               if (*match_info != NULL) {
+                                       CFRelease(*match_info);
+                                       *match_info = NULL;
+                               }
+
+                               minfo = CFDictionaryCreateMutable(kCFAllocatorDefault,
+                                                                 0,
+                                                                 &kCFTypeDictionaryKeyCallBacks,
+                                                                 &kCFTypeDictionaryValueCallBacks);
+
+                               type_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &type);
+                               CFDictionarySetValue(minfo, kSCNetworkConnectionOnDemandMatchInfoVPNType, type_num);
+                               CFRelease(type_num);
+                               if (matched_domain) {
+                                       CFDictionarySetValue(minfo, kSCNetworkConnectionOnDemandMatchInfoDomain, matched_domain);
+                               }
+                               CFDictionarySetValue(minfo,
+                                                    kSCNetworkConnectionOnDemandMatchInfoOnRetry,
+                                                    (usedOnDemandRetry ? kCFBooleanTrue : kCFBooleanFalse));
+
+                               *match_info = minfo;
+                       }
+
+                       if (probe_string != NULL) {
+                               if (*probe_string != NULL) {
+                                       CFRelease(*probe_string);
+                                       *probe_string = NULL;
+                               }
+
+                               if (matched_probe_string) {
+                                       *probe_string = CFRetain(matched_probe_string);
+                               }
+                       }
+
+                       result = trigger;
+
+                       /* If retry was requested, or we found Always match, trigger now */
+                       if (onDemandRetry || !usedOnDemandRetry) {
+                               if (triggerNow != NULL) {
+                                       *triggerNow = TRUE;
+                               }
+                               break;
+                       }
+
+                       /* If we matched the Retry list, but Always was requested,
+                        keep going through triggers in case one matches an Always */
+               }
+       }
+
+       if (result) {
+               CFRetain(result);
+       }
+
+       _SCErrorSet(sc_status);
+       return result;
+}
+
+
+static CFDictionaryRef
+__SCNetworkConnectionCopyTriggerWithService(CFDictionaryRef    configuration,
+                                           CFStringRef         service_id)
+{
+       CFArrayRef      triggers;
+       uint64_t        triggersCount   = 0;
+       int             triggersIndex;
+
+       triggers = CFDictionaryGetValue(configuration, kSCNetworkConnectionOnDemandTriggers);
+       triggersCount = isA_CFArray(triggers) ? CFArrayGetCount(triggers) : 0;
+       for (triggersIndex = 0; triggersIndex < triggersCount; triggersIndex++) {
+               CFDictionaryRef trigger;
+               CFStringRef     trigger_service_id;
+
+               trigger = CFArrayGetValueAtIndex(triggers, triggersIndex);
+               if (!isA_CFDictionary(trigger)) {
+                       // if not a valid "OnDemand" configuration
+                       continue;
+               }
+
+               trigger_service_id = CFDictionaryGetValue(trigger, kSCNetworkConnectionOnDemandServiceID);
+               if (isA_CFString(trigger_service_id) && CFEqual(trigger_service_id, service_id)) {
+                       CFRetain(trigger);
+                       return trigger;
+               }
+       }
+
+       return NULL;
+}
+
+
+__private_extern__ CFDictionaryRef
+__SCNetworkConnectionCopyTokenParameters(SCNetworkConnectionRef connection)
+{
+       SCNetworkConnectionPrivateRef   connectionPrivate       = (SCNetworkConnectionPrivateRef)connection;
+       CFDictionaryRef                 parameters              = NULL;
+       uint8_t                         params_buffer[PPP_MACH_MAX_INLINE_DATA];
+       uint32_t                        params_buffer_len       = sizeof(params_buffer);
+       int                             sc_status               = kSCStatusOK;
+       mach_port_t                     session_port;
+       kern_return_t                   status;
+
+       pthread_mutex_lock(&connectionPrivate->lock);
+
+       parameters = connectionPrivate->flow_divert_token_params;
+       if (parameters != NULL) {
+           CFRetain(parameters);
+           goto done;
+       }
+
+retry:
+       if (parameters != NULL) {
+               CFRelease(parameters);
+               parameters = NULL;
+       }
+
+       session_port = __SCNetworkConnectionSessionPort(connectionPrivate);
+       if (session_port == MACH_PORT_NULL) {
+               goto done;
+       }
+
+       status = pppcontroller_flow_divert_copy_token_parameters(session_port, params_buffer, &params_buffer_len);
+       if (status == KERN_SUCCESS) {
+               if (params_buffer_len > 0) {
+                       CFDataRef params_data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault,
+                                                                           params_buffer,
+                                                                           params_buffer_len,
+                                                                           kCFAllocatorNull);
+                       parameters = CFPropertyListCreateWithData(kCFAllocatorDefault,
+                                                                 params_data,
+                                                                 kCFPropertyListImmutable,
+                                                                 NULL,
+                                                                 NULL);
+                       CFRelease(params_data);
+               }
+       }
+
+       if (__SCNetworkConnectionNeedsRetry(connection, "__SCNetworkConnectionCopyTokenParameters()", status, &sc_status)) {
+               goto retry;
+       }
+
+       if (sc_status != kSCStatusOK) {
+               _SCErrorSet(sc_status);
+       }
+
+done:
+       if (parameters != NULL && connectionPrivate->flow_divert_token_params == NULL) {
+           connectionPrivate->flow_divert_token_params = (CFDictionaryRef)CFRetain(parameters);
+       }
+
+       pthread_mutex_unlock(&connectionPrivate->lock);
+
+       return parameters;
+}
+
+Boolean
+__SCNetworkConnectionCopyOnDemandInfoWithName(SCDynamicStoreRef                *storeP,
+                                             CFStringRef               hostName,
+                                             Boolean                   onDemandRetry,
+                                             CFStringRef               *connectionServiceID,
+                                             SCNetworkConnectionStatus *connectionStatus,
+                                             CFStringRef               *vpnRemoteAddress)      /*  CFDictionaryRef *info */
+{
+       CFDictionaryRef         configuration;
+       Boolean                 ok              = FALSE;
+       int                     sc_status       = kSCStatusOK;
+       CFDictionaryRef         trigger;
+       Boolean                 trigger_now     = FALSE;
+
+       configuration = __SCNetworkConnectionCopyOnDemandConfiguration();
+       if (configuration == NULL) {
+               _SCErrorSet(sc_status);
+               return ok;
+       }
+
+       trigger = __SCNetworkConnectionCopyMatchingTriggerWithName(configuration, hostName, 0, onDemandRetry, NULL, &trigger_now, NULL);
+       if (trigger != NULL && trigger_now) {
+               CFNumberRef                     num;
+               SCNetworkConnectionStatus       onDemandStatus  = kSCNetworkConnectionDisconnected;
+
+               ok = TRUE;
+
+               if (!CFDictionaryGetValueIfPresent(trigger, kSCNetworkConnectionOnDemandStatus, (const void **)&num) ||
+                   !isA_CFNumber(num) ||
+                   !CFNumberGetValue(num, kCFNumberSInt32Type, &onDemandStatus)) {
+                       onDemandStatus = kSCNetworkConnectionDisconnected;
+               }
+               if (connectionStatus != NULL) {
+                       *connectionStatus = onDemandStatus;
+               }
+
+               if (connectionServiceID != NULL) {
+                       *connectionServiceID = CFDictionaryGetValue(trigger, kSCNetworkConnectionOnDemandServiceID);
+                       *connectionServiceID = isA_CFString(*connectionServiceID);
+                       if ((*connectionServiceID != NULL) && (CFStringGetLength(*connectionServiceID) > 0)) {
+                               CFRetain(*connectionServiceID);
+                       } else {
+                               SCLog(TRUE, LOG_INFO, CFSTR("OnDemand%s configuration error, no serviceID"),
+                                     onDemandRetry ? " (on retry)" : "");
+                               *connectionServiceID = NULL;
+                               ok = FALSE;
+                       }
+               }
+
+               if (vpnRemoteAddress != NULL) {
+                       *vpnRemoteAddress = CFDictionaryGetValue(trigger, kSCNetworkConnectionOnDemandRemoteAddress);
+                       *vpnRemoteAddress = isA_CFString(*vpnRemoteAddress);
+                       if ((*vpnRemoteAddress != NULL) && (CFStringGetLength(*vpnRemoteAddress) > 0)) {
+                               CFRetain(*vpnRemoteAddress);
+                       } else {
+                               SCLog(TRUE, LOG_INFO, CFSTR("OnDemand%s configuration error, no server address"),
+                                     onDemandRetry ? " (on retry)" : "");
+                               *vpnRemoteAddress = NULL;
+                               ok = FALSE;
+                       }
+               }
+
+               if (!ok) {
+                       if ((connectionServiceID != NULL) && (*connectionServiceID != NULL)) {
+                               CFRelease(*connectionServiceID);
+                               *connectionServiceID = NULL;
+                       }
+                       if ((vpnRemoteAddress != NULL) && (*vpnRemoteAddress != NULL)) {
+                               CFRelease(*vpnRemoteAddress);
+                               *vpnRemoteAddress = NULL;
+                       }
+                       sc_status = kSCStatusFailed;
+               } else {
+                       if (_sc_debug || (debug > 0)) {
+                               SCLog(TRUE, LOG_INFO, CFSTR("OnDemand%s match, connection status = %d"),
+                                     onDemandRetry ? " (on retry)" : "",
+                                     onDemandStatus);
+                       }
+               }
+       }
+
+       if (trigger) {
+               CFRelease(trigger);
+       }
+
+//     if (_sc_debug || (debug > 0)) {
+//             SCLog(TRUE, LOG_INFO, CFSTR("OnDemand domain name(s) not matched"));
+//     }
+
+       if (configuration != NULL) CFRelease(configuration);
+       if (!ok) {
+               _SCErrorSet(sc_status);
+       }
+       return ok;
+}
+
+static Boolean
+__SCNetworkConnectionCopyUserPreferencesInternal(CFDictionaryRef       selectionOptions,
+                                                CFStringRef            *serviceID,
+                                                CFDictionaryRef        *userOptions)
+{
+       int             prefsChanged    = 1;
+       int             status;
+       Boolean         success         = FALSE;
+
+       if (notify_userprefs_token == -1) {
+               status = notify_register_check(k_NetworkConnect_Notification, &notify_userprefs_token);
+               if (status != NOTIFY_STATUS_OK) {
+                       SCLog(TRUE, LOG_ERR, CFSTR("notify_register_check() failed, status=%lu"), status);
+                       (void)notify_cancel(notify_userprefs_token);
+                       notify_userprefs_token = -1;
+               } else {
+                       // clear the "something has changed" state
+                       (void) notify_check(notify_userprefs_token, &prefsChanged);
+                       prefsChanged = 1;
+               }
+       }
+       if (notify_userprefs_token != -1) {
+               status = notify_check(notify_userprefs_token, &prefsChanged);
+               if (status != NOTIFY_STATUS_OK) {
+                       SCLog(TRUE, LOG_ERR, CFSTR("notify_check() failed, status=%lu"), status);
+                       (void)notify_cancel(notify_userprefs_token);
+                       notify_userprefs_token = -1;
+               }
+       }
+
+
+       *serviceID = NULL;
+       *userOptions = NULL;
 
-                       domain = CFArrayGetValueAtIndex(domains, domainsIndex);
-                       if (!isA_CFString(domain)) {
-                               // if not a valid match domain
+       if (selectionOptions != NULL) {
+               Boolean         catchAllFound   = FALSE;
+               CFIndex         catchAllService = 0;
+               CFIndex         catchAllConfig  = 0;
+               CFStringRef     hostName        = NULL;
+               CFStringRef     priority        = NULL;
+               CFArrayRef      serviceNames    = NULL;
+               CFDictionaryRef services        = NULL;
+               CFIndex         serviceIndex;
+               CFIndex         servicesCount;
+
+               hostName = CFDictionaryGetValue(selectionOptions, kSCNetworkConnectionSelectionOptionOnDemandHostName);
+               if (hostName == NULL) {
+                       hostName = CFDictionaryGetValue(selectionOptions, kSCPropNetPPPOnDemandHostName);
+               }
+               hostName = isA_CFString(hostName);
+               if (hostName == NULL)
+                       goto done_selection;    // if no hostname for matching
+
+               priority = CFDictionaryGetValue(selectionOptions, kSCPropNetPPPOnDemandPriority);
+               if (!isA_CFString(priority))
+                       priority = kSCValNetPPPOnDemandPriorityDefault;
+
+
+               if (!isA_CFArray(serviceNames))
+                       goto done_selection;
+
+
+               if (!isA_CFDictionary(services)) {
+                       goto done_selection;
+               }
+
+               servicesCount = CFArrayGetCount(serviceNames);
+               for (serviceIndex = 0; serviceIndex < servicesCount; serviceIndex++) {
+                       CFIndex         configIndex;
+                       CFIndex         configsCount;
+                       CFArrayRef      serviceConfigs;
+                       CFStringRef     serviceName;
+                       int             val;
+
+                       serviceName = CFArrayGetValueAtIndex(serviceNames, serviceIndex);
+                       if (!isA_CFString(serviceName)) {
+                               continue;
+                       }
+
+                       serviceConfigs = CFDictionaryGetValue(services, serviceName);
+                       if (!isA_CFArray(serviceConfigs)) {
                                continue;
                        }
 
-                       if (_SC_domainEndsWithDomain(hostName, domain)) {
-                               CFArrayRef                      exceptions;
-                               int                             exceptionsCount;
-                               int                             exceptionsIndex;
-                               CFNumberRef                     num;
-                               SCNetworkConnectionStatus       onDemandStatus  = kSCNetworkConnectionDisconnected;
+                       configsCount = CFArrayGetCount(serviceConfigs);
+                       for (configIndex = 0; configIndex < configsCount; configIndex++) {
+                               CFNumberRef     autodial;
+                               CFDictionaryRef config;
+                               CFDictionaryRef pppConfig;
+
+                               config = CFArrayGetValueAtIndex(serviceConfigs, configIndex);
+                               if (!isA_CFDictionary(config)) {
+                                       continue;
+                               }
+
+                               pppConfig = CFDictionaryGetValue(config, kSCEntNetPPP);
+                               if (!isA_CFDictionary(pppConfig)) {
+                                       continue;
+                               }
+
+                               autodial = CFDictionaryGetValue(pppConfig, kSCPropNetPPPOnDemandEnabled);
+                               if (!isA_CFNumber(autodial)) {
+                                       continue;
+                               }
+
+                               CFNumberGetValue(autodial, kCFNumberIntType, &val);
+                               if (val) {
+                                       CFArrayRef      domains;
+                                       CFIndex         domainsCount;
+                                       CFIndex         domainsIndex;
 
-                               // we have a matching domain, check against exception list
-                               exceptions = CFDictionaryGetValue(trigger, kSCNetworkConnectionOnDemandMatchDomainsNever);
-                               exceptionsCount = isA_CFArray(exceptions) ? CFArrayGetCount(exceptions) : 0;
-                               for (exceptionsIndex = 0; exceptionsIndex < exceptionsCount; exceptionsIndex++) {
-                                       CFStringRef     exception;
+                                       /* we found an conditional connection enabled configuration */
 
-                                       exception = CFArrayGetValueAtIndex(exceptions, exceptionsIndex);
-                                       if (!isA_CFString(exception)) {
-                                               // if not a valid match exception
+                                       /* check domain */
+                                       domains = CFDictionaryGetValue(pppConfig, kSCPropNetPPPOnDemandDomains);
+                                       if (!isA_CFArray(domains)) {
                                                continue;
                                        }
 
-                                       if (_SC_domainEndsWithDomain(hostName, exception)) {
-                                               // found matching exception
-                                               if (_sc_debug || (debug > 0)) {
-                                                       SCLog(TRUE, LOG_INFO, CFSTR("OnDemand match exception"));
+                                       domainsCount = CFArrayGetCount(domains);
+                                       for (domainsIndex = 0; domainsIndex < domainsCount; domainsIndex++) {
+                                               CFStringRef     domain;
+
+                                               domain = CFArrayGetValueAtIndex(domains, domainsIndex);
+                                               if (!isA_CFString(domain)) {
+                                                       continue;
+                                               }
+
+                                               if (!catchAllFound &&
+                                                   (CFStringCompare(domain, CFSTR(""), 0) == kCFCompareEqualTo
+                                                       || CFStringCompare(domain, CFSTR("."), 0) == kCFCompareEqualTo))
+                                               {
+                                                       // found a catch all
+                                                       catchAllFound = TRUE;
+                                                       catchAllService = serviceIndex;
+                                                       catchAllConfig = configIndex;
+                                               }
+
+                                               if (_SC_domainEndsWithDomain(hostName, domain)) {
+                                                       // found matching configuration
+                                                       *serviceID = serviceName;
+                                                       CFRetain(*serviceID);
+                                                       *userOptions = CFDictionaryCreateMutableCopy(NULL, 0, config);
+                                                       CFDictionarySetValue((CFMutableDictionaryRef)*userOptions, kSCNetworkConnectionSelectionOptionOnDemandHostName, hostName);
+                                                       CFDictionarySetValue((CFMutableDictionaryRef)*userOptions, kSCPropNetPPPOnDemandPriority, priority);
+                                                       addPasswordFromKeychain(*serviceID, userOptions);
+                                                       success = TRUE;
+                                                       goto done_selection;
                                                }
-                                               goto done;
                                        }
                                }
+                       }
+               }
 
-                               // if we have a matching domain and there were no exceptions
-                               // then we pass back the OnDemand info
+               // config not found, do we have a catchall ?
+               if (catchAllFound) {
+                       CFDictionaryRef config;
+                       CFArrayRef      serviceConfigs;
+                       CFStringRef     serviceName;
 
-                               ok = TRUE;
+                       serviceName = CFArrayGetValueAtIndex(serviceNames, catchAllService);
+                       serviceConfigs = CFDictionaryGetValue(services, serviceName);
+                       config = CFArrayGetValueAtIndex(serviceConfigs, catchAllConfig);
 
-                               if (!CFDictionaryGetValueIfPresent(trigger,
-                                                                  kSCNetworkConnectionOnDemandStatus,
-                                                                  (const void **)&num) ||
-                                   !isA_CFNumber(num) ||
-                                   !CFNumberGetValue(num, kCFNumberSInt32Type, &onDemandStatus)) {
-                                       onDemandStatus = kSCNetworkConnectionDisconnected;
-                               }
-                               if (connectionStatus != NULL) {
-                                       *connectionStatus = onDemandStatus;
-                               }
+                       *serviceID = serviceName;
+                       CFRetain(*serviceID);
+                       *userOptions = CFDictionaryCreateMutableCopy(NULL, 0, config);
+                       CFDictionarySetValue((CFMutableDictionaryRef)*userOptions, kSCNetworkConnectionSelectionOptionOnDemandHostName, hostName);
+                       CFDictionarySetValue((CFMutableDictionaryRef)*userOptions, kSCPropNetPPPOnDemandPriority, priority);
+                       addPasswordFromKeychain(*serviceID, userOptions);
+                       success = TRUE;
+                       goto done_selection;
+               }
 
-                               if (connectionServiceID != NULL) {
-                                       *connectionServiceID = CFDictionaryGetValue(trigger, kSCNetworkConnectionOnDemandServiceID);
-                                       *connectionServiceID = isA_CFString(*connectionServiceID);
-                                       if ((*connectionServiceID != NULL) && (CFStringGetLength(*connectionServiceID) > 0)) {
-                                               CFRetain(*connectionServiceID);
-                                       } else {
-                                               SCLog(TRUE, LOG_INFO,
-                                                     CFSTR("OnDemand%s configuration error, no serviceID"),
-                                                     onDemandRetry ? " (on retry)" : "");
-
-                                               *connectionServiceID = NULL;
-                                               ok = FALSE;
-                                       }
-                               }
+           done_selection:
 
-                               if (vpnRemoteAddress != NULL) {
-                                       *vpnRemoteAddress = CFDictionaryGetValue(trigger, kSCNetworkConnectionOnDemandRemoteAddress);
-                                       *vpnRemoteAddress = isA_CFString(*vpnRemoteAddress);
-                                       if ((*vpnRemoteAddress != NULL) && (CFStringGetLength(*vpnRemoteAddress) > 0)) {
-                                               CFRetain(*vpnRemoteAddress);
-                                       } else {
-                                               SCLog(TRUE, LOG_INFO,
-                                                     CFSTR("OnDemand%s configuration error, no server address"),
-                                                     onDemandRetry ? " (on retry)" : "");
-
-                                               *vpnRemoteAddress = NULL;
-                                               ok = FALSE;
-                                       }
-                               }
+               if (serviceNames) {
+                       CFRelease(serviceNames);
+               }
+               if (services) {
+                       CFRelease(services);
+               }
 
-                               if (!ok) {
-                                       if ((connectionServiceID != NULL) && (*connectionServiceID != NULL)) {
-                                               CFRelease(*connectionServiceID);
-                                               *connectionServiceID = NULL;
-                                       }
-                                       if ((vpnRemoteAddress != NULL) && (*vpnRemoteAddress != NULL)) {
-                                               CFRelease(*vpnRemoteAddress);
-                                               *vpnRemoteAddress = NULL;
-                                       }
-                                       continue;
-                               }
+               if (debug > 1) {
+                       SCLog(TRUE, LOG_DEBUG, CFSTR("SCNetworkConnectionCopyUserPreferences %@"), success ? CFSTR("succeeded") : CFSTR("failed"));
+                       SCLog(TRUE, LOG_DEBUG, CFSTR("Selection options: %@"), selectionOptions);
+               }
 
-                               if (_sc_debug || (debug > 0)) {
-                                       SCLog(TRUE, LOG_INFO,
-                                             CFSTR("OnDemand%s match, connection status = %d"),
-                                             onDemandRetry ? " (on retry)" : "",
-                                             onDemandStatus);
-                               }
+               return success;
+       }
 
-                               goto done;
+       /* we don't have selection options */
+
+       // (1) Figure out which service ID we care about, allocate it into passed "serviceID"
+       success = SCNetworkConnectionPrivateCopyDefaultServiceIDForDial(serviceID);
+
+       if (success && (*serviceID != NULL)) {
+               // (2) Get the list of user data for this service ID
+               CFPropertyListRef       userServices    = NULL;
+
+
+               // (3) We are expecting an array if the user has defined records for this service ID or NULL if the user hasn't
+               if (userServices != NULL) {
+                       if (isA_CFArray(userServices)) {
+                               // (4) Get the default set of user options for this service
+                               success = SCNetworkConnectionPrivateCopyDefaultUserOptionsFromArray((CFArrayRef)userServices,
+                                                                                                   userOptions);
+                               if(success && (userOptions != NULL)) {
+                                       addPasswordFromKeychain(*serviceID, userOptions);
+                               }
+                       } else {
+                               SCLog(TRUE, LOG_DEBUG, CFSTR("Error, userServices are not of type CFArray!"));
                        }
+
+                       CFRelease(userServices); // this is OK because SCNetworkConnectionPrivateISExpectedCFType() checks for NULL
                }
        }
 
-//     if (_sc_debug || (debug > 0)) {
-//             SCLog(TRUE, LOG_INFO, CFSTR("OnDemand domain name(s) not matched"));
-//     }
-
-    done :
+       if (debug > 1) {
+               SCLog(TRUE, LOG_DEBUG, CFSTR("SCNetworkConnectionCopyUserPreferences %@, no selection options"), success ? CFSTR("succeeded") : CFSTR("failed"));
+       }
 
-       if (configuration != NULL) CFRelease(configuration);
-       return ok;
+       return success;
 }
 
 
@@ -2202,10 +3593,7 @@ SCNetworkConnectionCopyUserPreferences(CFDictionaryRef   selectionOptions,
                                       CFStringRef      *serviceID,
                                       CFDictionaryRef  *userOptions)
 {
-       int                     prefsChanged    = 1;
-       SCDynamicStoreRef       session         = NULL;
-       Boolean                 success         = FALSE;
-       int                     status;
+       Boolean success = FALSE;
 
 
        /* initialize runtime */
@@ -2218,14 +3606,14 @@ SCNetworkConnectionCopyUserPreferences(CFDictionaryRef  selectionOptions,
                hostName = CFDictionaryGetValue(selectionOptions, kSCNetworkConnectionSelectionOptionOnDemandHostName);
                if (isA_CFString(hostName)) {
                        CFStringRef                     connectionServiceID     = NULL;
-                       SCNetworkConnectionStatus       connectionStatus;
+                       SCNetworkConnectionStatus       connectionStatus        = kSCNetworkConnectionInvalid;
                        Boolean                         onDemandRetry;
                        CFTypeRef                       val;
 
                        val = CFDictionaryGetValue(selectionOptions, kSCNetworkConnectionSelectionOptionOnDemandRetry);
                        onDemandRetry = isA_CFBoolean(val) ? CFBooleanGetValue(val) : TRUE;
 
-                       success = __SCNetworkConnectionCopyOnDemandInfoWithName(&session,
+                       success = __SCNetworkConnectionCopyOnDemandInfoWithName(NULL,
                                                                                hostName,
                                                                                onDemandRetry,
                                                                                &connectionServiceID,
@@ -2240,9 +3628,6 @@ SCNetworkConnectionCopyUserPreferences(CFDictionaryRef    selectionOptions,
 
                        if (success) {
                                // if the hostname matches an OnDemand domain
-                               if (session != NULL) {
-                                       CFRelease(session);
-                               }
                                if (connectionStatus == kSCNetworkConnectionConnected) {
                                        // if we are already connected
                                        if (connectionServiceID != NULL) {
@@ -2258,232 +3643,580 @@ SCNetworkConnectionCopyUserPreferences(CFDictionaryRef        selectionOptions,
                        } else if (!onDemandRetry) {
                                // if the hostname does not match an OnDemand domain and we have
                                // not yet issued an initial DNS query (i.e. it's not a query
-                               // being retried after the VPN has been established) than we're
+                               // being retried after the VPN has been established) then we're
                                // done
-                               if (session != NULL) {
-                                       CFRelease(session);
-                               }
                                return FALSE;
                        }
                }
        }
 
-       if (notify_userprefs_token == -1) {
-               status = notify_register_check(k_NetworkConnect_Notification, &notify_userprefs_token);
-               if (status != NOTIFY_STATUS_OK) {
-                       SCLog(TRUE, LOG_ERR, CFSTR("notify_register_check() failed, status=%lu"), status);
-                       (void)notify_cancel(notify_userprefs_token);
-                       notify_userprefs_token = -1;
+       return __SCNetworkConnectionCopyUserPreferencesInternal(selectionOptions, serviceID, userOptions);
+}
+
+
+Boolean
+SCNetworkConnectionOnDemandShouldRetryOnFailure (SCNetworkConnectionRef connection)
+{
+       SCNetworkConnectionPrivateRef   connectionPrivate       = (SCNetworkConnectionPrivateRef)connection;
+       CFDictionaryRef                 match_info              = NULL;
+
+       if (!isA_SCNetworkConnection(connection)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               goto fail;
+       }
+
+       if (connectionPrivate->service == NULL) {
+               _SCErrorSet(kSCStatusConnectionNoService);
+               goto fail;
+       }
+
+       if (isA_CFDictionary(connectionPrivate->on_demand_user_options)) {
+               match_info = CFDictionaryGetValue(connectionPrivate->on_demand_user_options, kSCNetworkConnectionSelectionOptionOnDemandMatchInfo);
+               if (isA_CFDictionary(match_info)) {
+                       CFBooleanRef onRetry = CFDictionaryGetValue(match_info, kSCNetworkConnectionOnDemandMatchInfoOnRetry);
+                       if (isA_CFBoolean(onRetry)) {
+                               return CFBooleanGetValue(onRetry);
+                       }
+               }
+       }
+
+    fail:
+       return FALSE;
+}
+
+
+// Mask is optional in routes dictionary; if not present, whole addresses are matched
+Boolean
+__SCNetworkConnectionIPv4AddressMatchesRoutes (struct sockaddr_in *addr_in, CFDictionaryRef routes)
+{
+       int             count;
+       int             i;
+       CFDataRef       maskData        = NULL;
+       struct in_addr  *maskDataArray;
+       CFDataRef       routeaddrData   = NULL;
+       struct in_addr  *routeaddrDataArray;
+
+       if (!isA_CFDictionary(routes)) {
+               return FALSE;
+       }
+
+       routeaddrData = CFDictionaryGetValue(routes, kSCNetworkConnectionNetworkInfoAddresses);
+       maskData = CFDictionaryGetValue(routes, kSCNetworkConnectionNetworkInfoMasks);
+
+       /* routeaddrData and maskData are packed arrays of addresses; make sure they have the same length */
+       if (!isA_CFData(routeaddrData) || (maskData && (!isA_CFData(maskData) || CFDataGetLength(routeaddrData) != CFDataGetLength(maskData)))) {
+               return FALSE;
+       }
+
+       routeaddrDataArray = (struct in_addr*)(void*)CFDataGetBytePtr(routeaddrData);
+       if (maskData) {
+               maskDataArray = (struct in_addr*)(void*)CFDataGetBytePtr(maskData);
+       }
+
+       count = CFDataGetLength(routeaddrData) / sizeof(struct in_addr);
+
+       for (i=0; i<count; i++) {
+               struct in_addr  routeAddr       = *routeaddrDataArray;
+
+               if (maskData) {
+                       struct in_addr  mask    = *maskDataArray;
+
+                       if ((addr_in->sin_addr.s_addr & mask.s_addr) == (routeAddr.s_addr & mask.s_addr)) {
+                               return TRUE;
+                       }
+                       maskDataArray++;
                } else {
-                       // clear the "something has changed" state
-                       (void) notify_check(notify_userprefs_token, &prefsChanged);
-                       prefsChanged = 1;
+                       if (addr_in->sin_addr.s_addr == routeAddr.s_addr) {
+                               return TRUE;
+                       }
                }
+               routeaddrDataArray++;
        }
-       if (notify_userprefs_token != -1) {
-               status = notify_check(notify_userprefs_token, &prefsChanged);
-               if (status != NOTIFY_STATUS_OK) {
-                       SCLog(TRUE, LOG_ERR, CFSTR("notify_check() failed, status=%lu"), status);
-                       (void)notify_cancel(notify_userprefs_token);
-                       notify_userprefs_token = -1;
+       return FALSE;
+}
+
+
+void
+__SCNetworkConnectionMaskIPv6Address(struct in6_addr *addr, struct in6_addr *mask)
+{
+       int     i;
+
+       for (i = 0; i < sizeof(struct in6_addr); i++)
+               addr->s6_addr[i] &= mask->s6_addr[i];
+}
+
+
+// Mask is optional in routes dictionary; if not present, whole addresses are matched
+Boolean
+__SCNetworkConnectionIPv6AddressMatchesRoutes (struct sockaddr_in6 *addr_in6, CFDictionaryRef routes)
+{
+       int             count;
+       int             i;
+       CFDataRef       maskData        = NULL;
+       struct in6_addr *maskDataArray;
+       CFDataRef       routeaddrData   = NULL;
+       struct in6_addr *routeaddrDataArray;
+
+       if (!isA_CFDictionary(routes)) {
+               return FALSE;
+       }
+
+       routeaddrData = CFDictionaryGetValue(routes, kSCNetworkConnectionNetworkInfoAddresses);
+       maskData = CFDictionaryGetValue(routes, kSCNetworkConnectionNetworkInfoMasks);
+
+       /* routeaddrData and maskData are packed arrays of addresses; make sure they have the same length */
+       if (!isA_CFData(routeaddrData) || (maskData && (!isA_CFData(maskData) || CFDataGetLength(routeaddrData) != CFDataGetLength(maskData)))) {
+               return FALSE;
+       }
+
+       routeaddrDataArray = (struct in6_addr*)(void*)CFDataGetBytePtr(routeaddrData);
+       if (maskData) {
+               maskDataArray = (struct in6_addr*)(void*)CFDataGetBytePtr(maskData);
+       }
+
+       count = CFDataGetLength(routeaddrData) / sizeof(struct in6_addr);
+
+       for (i=0; i<count; i++) {
+               if (maskData) {
+                       struct in6_addr cmpAddr;
+                       struct in6_addr *mask = maskDataArray;
+                       struct in6_addr routeAddr;
+
+                       memcpy(&routeAddr, routeaddrDataArray, sizeof(routeAddr));
+                       memcpy(&cmpAddr, &addr_in6->sin6_addr, sizeof(cmpAddr));
+                       __SCNetworkConnectionMaskIPv6Address(&routeAddr, mask);
+                       __SCNetworkConnectionMaskIPv6Address(&cmpAddr, mask);
+                       maskDataArray++;
+                       if (!memcmp(&routeAddr, &cmpAddr, sizeof(routeAddr))) {
+                               return TRUE;
+                       }
+               } else {
+                       if (!memcmp(routeaddrDataArray, &addr_in6->sin6_addr, sizeof(struct in6_addr))) {
+                               return TRUE;
+                       }
                }
+
+               routeaddrDataArray++;
        }
+       return FALSE;
+}
 
 
-       *serviceID = NULL;
-       *userOptions = NULL;
+static Boolean
+__SCNetworkConnectionAddressMatchesRedirectedDNS(CFDictionaryRef trigger, const struct sockaddr *input_addr)
+{
+       CFBooleanRef redirectedRef = CFDictionaryGetValue(trigger, kSCNetworkConnectionOnDemandDNSRedirectDetected);
 
-       if (session == NULL) {
-               session = SCDynamicStoreCreate(NULL, CFSTR("SCNetworkConnection"), NULL, NULL);
+       if (isA_CFBoolean(redirectedRef) && CFBooleanGetValue(redirectedRef)) {
+               /* DNS is redirected. Look for address list. */
+               CFDictionaryRef redirectedAddressesRef = CFDictionaryGetValue(trigger, kSCNetworkConnectionOnDemandDNSRedirectedAddresses);
+
+               if (isA_CFDictionary(redirectedAddressesRef)) {
+                       if (input_addr->sa_family == AF_INET) {
+                               return __SCNetworkConnectionIPv4AddressMatchesRoutes((struct sockaddr_in*)(void*)input_addr, CFDictionaryGetValue(redirectedAddressesRef, kSCNetworkConnectionNetworkInfoIPv4));
+                       } else if (input_addr->sa_family == AF_INET6) {
+                               return __SCNetworkConnectionIPv6AddressMatchesRoutes((struct sockaddr_in6*)(void*)input_addr, CFDictionaryGetValue(redirectedAddressesRef, kSCNetworkConnectionNetworkInfoIPv6));
+                       }
+               }
        }
-       if (session == NULL) {
-               SCLog(TRUE, LOG_ERR, CFSTR("Error,  SCNetworkConnectionCopyUserPreferences, SCDynamicStoreCreate() returned NULL!"));
+
+       return FALSE;
+}
+
+/* If the required probe has failed, we need to tunnel the address. Equivalent to redirected DNS. */
+static Boolean
+__SCNetworkConnectionRequiredProbeFailed (CFDictionaryRef trigger, CFStringRef probeString)
+{
+       CFDictionaryRef probeResults = NULL;
+
+       if (!isA_CFString(probeString)) {
                return FALSE;
        }
 
-       if (selectionOptions != NULL) {
-               Boolean         catchAllFound   = FALSE;
-               CFIndex         catchAllService = 0;
-               CFIndex         catchAllConfig  = 0;
-               CFStringRef     hostName        = NULL;
-               CFStringRef     priority        = NULL;
-               CFArrayRef      serviceNames    = NULL;
-               CFDictionaryRef services        = NULL;
-               CFIndex         serviceIndex;
-               CFIndex         servicesCount;
+       probeResults = CFDictionaryGetValue(trigger, kSCNetworkConnectionOnDemandProbeResults);
+       if (!isA_CFDictionary(probeResults)) {
+               return TRUE;
+       }
 
-               hostName = CFDictionaryGetValue(selectionOptions, kSCNetworkConnectionSelectionOptionOnDemandHostName);
-               if (hostName == NULL) {
-                       hostName = CFDictionaryGetValue(selectionOptions, kSCPropNetPPPOnDemandHostName);
-               }
-               hostName = isA_CFString(hostName);
-               if (hostName == NULL)
-                       goto done_selection;    // if no hostname for matching
+       CFBooleanRef result = CFDictionaryGetValue(probeResults, probeString);
 
-               priority = CFDictionaryGetValue(selectionOptions, kSCPropNetPPPOnDemandPriority);
-               if (!isA_CFString(priority))
-                       priority = kSCValNetPPPOnDemandPriorityDefault;
+       /* Only a value of kCFBooleanFalse marks the probe as failed  */
+       return (isA_CFBoolean(result) && !CFBooleanGetValue(result));
+}
 
+Boolean
+SCNetworkConnectionCanTunnelAddress (SCNetworkConnectionRef connection, const struct sockaddr *address, Boolean *startImmediately)
+{
+       SCNetworkConnectionPrivateRef   connectionPrivate       = (SCNetworkConnectionPrivateRef)connection;
+       CFStringRef                     serviceID               = NULL;
+       CFDictionaryRef                 configuration           = NULL;
+       CFDictionaryRef                 trigger                 = NULL;
+       CFDictionaryRef                 tunneledNetworks        = NULL;
+       sa_family_t                     address_family          = AF_UNSPEC;
+       Boolean                         success                 = FALSE;
 
-               if (!isA_CFArray(serviceNames))
-                       goto done_selection;
+       if (startImmediately) {
+               *startImmediately = FALSE;
+       }
 
+       if (address == NULL) {
+               goto done;
+       }
 
-               if (!isA_CFDictionary(services))
-                       goto done_selection;
+       address_family = address->sa_family;
+       if (address_family != AF_INET && address_family != AF_INET6) {
+               goto done;
+       }
 
-               servicesCount = CFArrayGetCount(serviceNames);
-               for (serviceIndex = 0; serviceIndex < servicesCount; serviceIndex++) {
-                       CFIndex         configIndex;
-                       CFIndex         configsCount;
-                       CFArrayRef      serviceConfigs;
-                       CFStringRef     serviceName;
-                       int             val;
+       if (!isA_SCNetworkConnection(connection)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               goto done;
+       }
 
-                       serviceName = CFArrayGetValueAtIndex(serviceNames, serviceIndex);
-                       if (!isA_CFString(serviceName))
-                               continue;
+       if (connectionPrivate->service == NULL) {
+               _SCErrorSet(kSCStatusConnectionNoService);
+               goto done;
+       }
 
-                       serviceConfigs = CFDictionaryGetValue(services, serviceName);
-                       if (!isA_CFArray(serviceConfigs))
-                               continue;
+       serviceID = SCNetworkServiceGetServiceID(connectionPrivate->service);
+       if (!isA_CFString(serviceID)) {
+               goto done;
+       }
 
-                       configsCount = CFArrayGetCount(serviceConfigs);
-                       for (configIndex = 0; configIndex < configsCount; configIndex++) {
-                               CFNumberRef     autodial;
-                               CFDictionaryRef config;
-                               CFDictionaryRef pppConfig;
+       configuration = __SCNetworkConnectionCopyOnDemandConfiguration();
+       if (configuration == NULL) {
+               goto done;
+       }
 
-                               config = CFArrayGetValueAtIndex(serviceConfigs, configIndex);
-                               if (!isA_CFDictionary(config))
-                                       continue;
+       trigger = __SCNetworkConnectionCopyTriggerWithService(configuration, serviceID);
+       if (trigger == NULL) {
+               goto done;
+       }
 
-                               pppConfig = CFDictionaryGetValue(config, kSCEntNetPPP);
-                               if (!isA_CFDictionary(pppConfig))
-                                       continue;
+       if (__SCNetworkConnectionRequiredProbeFailed(trigger, connectionPrivate->on_demand_required_probe)) {
+               /* If probe failed, we can't trust DNS - connect now */
+               if (startImmediately) {
+                       *startImmediately = TRUE;
+               }
+               success = TRUE;
+               goto done;
+       }
 
-                               autodial = CFDictionaryGetValue(pppConfig, kSCPropNetPPPOnDemandEnabled);
-                               if (!isA_CFNumber(autodial))
-                                       continue;
+       if (__SCNetworkConnectionAddressMatchesRedirectedDNS(trigger, address)) {
+               if (startImmediately) {
+                       *startImmediately = TRUE;
+               }
+               success = TRUE;
+               goto done;
+       }
 
-                               CFNumberGetValue(autodial, kCFNumberIntType, &val);
-                               if (val) {
-                                       CFArrayRef      domains;
-                                       CFIndex         domainsCount;
-                                       CFIndex         domainsIndex;
+       tunneledNetworks = CFDictionaryGetValue(trigger, kSCNetworkConnectionOnDemandTunneledNetworks);
+       if (!isA_CFDictionary(tunneledNetworks)) {
+               goto done;
+       }
 
-                                       /* we found an conditional connection enabled configuration */
+       if (address_family == AF_INET) {
+               CFDictionaryRef ip_dict;
+               Boolean matches = FALSE;
+               struct sockaddr_in *addr_in = (struct sockaddr_in *)(void*)address;
 
-                                       /* check domain */
-                                       domains = CFDictionaryGetValue(pppConfig, kSCPropNetPPPOnDemandDomains);
-                                       if (!isA_CFArray(domains))
-                                               continue;
+               ip_dict = CFDictionaryGetValue(tunneledNetworks, kSCNetworkConnectionNetworkInfoIPv4);
+               if (!isA_CFDictionary(ip_dict)) {
+                       goto done;
+               }
 
-                                       domainsCount = CFArrayGetCount(domains);
-                                       for (domainsIndex = 0; domainsIndex < domainsCount; domainsIndex++) {
-                                               CFStringRef     domain;
+               matches = __SCNetworkConnectionIPv4AddressMatchesRoutes(addr_in, CFDictionaryGetValue(ip_dict, kSCNetworkConnectionNetworkInfoIncludedRoutes));
 
-                                               domain = CFArrayGetValueAtIndex(domains, domainsIndex);
-                                               if (!isA_CFString(domain))
-                                                       continue;
+               if (matches) {
+                       if (!__SCNetworkConnectionIPv4AddressMatchesRoutes(addr_in, CFDictionaryGetValue(ip_dict, kSCNetworkConnectionNetworkInfoExcludedRoutes))) {
+                               success = TRUE;
+                               goto done;
+                       }
+               }
+       } else {
+               CFDictionaryRef ip6_dict;
+               Boolean matches = FALSE;
+               struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)(void*)address;
 
-                                               if (!catchAllFound &&
-                                                   (CFStringCompare(domain, CFSTR(""), 0) == kCFCompareEqualTo
-                                                       || CFStringCompare(domain, CFSTR("."), 0) == kCFCompareEqualTo)) {
-                                                       // found a catch all
-                                                       catchAllFound = TRUE;
-                                                       catchAllService = serviceIndex;
-                                                       catchAllConfig = configIndex;
-                                               }
+               ip6_dict = CFDictionaryGetValue(tunneledNetworks, kSCNetworkConnectionNetworkInfoIPv6);
+               if (!isA_CFDictionary(ip6_dict)) {
+                       goto done;
+               }
 
-                                               if (_SC_domainEndsWithDomain(hostName, domain)) {
-                                                       // found matching configuration
-                                                       *serviceID = serviceName;
-                                                       CFRetain(*serviceID);
-                                                       *userOptions = CFDictionaryCreateMutableCopy(NULL, 0, config);
-                                                       CFDictionarySetValue((CFMutableDictionaryRef)*userOptions, kSCNetworkConnectionSelectionOptionOnDemandHostName, hostName);
-                                                       CFDictionarySetValue((CFMutableDictionaryRef)*userOptions, kSCPropNetPPPOnDemandPriority, priority);
-                                                       addPasswordFromKeychain(session, *serviceID, userOptions);
-                                                       success = TRUE;
-                                                       goto done_selection;
-                                               }
-                                       }
-                               }
+               matches = __SCNetworkConnectionIPv6AddressMatchesRoutes(addr_in6, CFDictionaryGetValue(ip6_dict, kSCNetworkConnectionNetworkInfoIncludedRoutes));
+
+               if (matches) {
+                       if (!__SCNetworkConnectionIPv6AddressMatchesRoutes(addr_in6, CFDictionaryGetValue(ip6_dict, kSCNetworkConnectionNetworkInfoExcludedRoutes))) {
+                               success = TRUE;
+                               goto done;
                        }
                }
+       }
+done:
+       if (configuration) {
+               CFRelease(configuration);
+       }
+       if (trigger) {
+               CFRelease(trigger);
+       }
+       return success;
+}
 
-               // config not found, do we have a catchall ?
-               if (catchAllFound) {
-                       CFDictionaryRef config;
-                       CFArrayRef      serviceConfigs;
-                       CFStringRef     serviceName;
+Boolean
+SCNetworkConnectionSelectServiceWithOptions(SCNetworkConnectionRef connection, CFDictionaryRef selectionOptions)
+{
+       CFStringRef                     account_identifier      = NULL;
+       CFDictionaryRef                 configuration           = NULL;
+       SCNetworkConnectionPrivateRef   connectionPrivate       = (SCNetworkConnectionPrivateRef)connection;
+       CFDictionaryRef                 found_trigger           = NULL;
+       CFStringRef                     host_name               = NULL;
+       Boolean                         is_retry                = TRUE;
+       CFDictionaryRef                 match_info              = NULL;
+       CFMutableDictionaryRef          new_user_options        = NULL;
+       SCNetworkConnectionStatus       on_demand_status        = kSCNetworkConnectionInvalid;
+       CFStringRef                     requiredProbe           = NULL;
+       CFStringRef                     service_id              = NULL;
+       Boolean                         skip_prefs              = FALSE;
+       Boolean                         success                 = TRUE;
+       CFDictionaryRef                 user_options            = NULL;
 
-                       serviceName = CFArrayGetValueAtIndex(serviceNames, catchAllService);
-                       serviceConfigs = CFDictionaryGetValue(services, serviceName);
-                       config = CFArrayGetValueAtIndex(serviceConfigs, catchAllConfig);
+       if (!isA_SCNetworkConnection(connection)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               success = FALSE;
+               goto done;
+       }
 
-                       *serviceID = serviceName;
-                       CFRetain(*serviceID);
-                       *userOptions = CFDictionaryCreateMutableCopy(NULL, 0, config);
-                       CFDictionarySetValue((CFMutableDictionaryRef)*userOptions, kSCNetworkConnectionSelectionOptionOnDemandHostName, hostName);
-                       CFDictionarySetValue((CFMutableDictionaryRef)*userOptions, kSCPropNetPPPOnDemandPriority, priority);
-                       addPasswordFromKeychain(session, *serviceID, userOptions);
-                       success = TRUE;
-                       goto done_selection;
+       /* Can't call this on a connection that is already associated with a service */
+       if (connectionPrivate->service != NULL) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               success = FALSE;
+               goto done;
+       }
+
+       if (isA_CFDictionary(selectionOptions)) {
+               CFBooleanRef no_user_prefs = CFDictionaryGetValue(selectionOptions, kSCNetworkConnectionSelectionOptionNoUserPrefs);
+               CFBooleanRef retry = CFDictionaryGetValue(selectionOptions, kSCNetworkConnectionSelectionOptionOnDemandRetry);
+
+               account_identifier = CFDictionaryGetValue(selectionOptions, kSCNetworkConnectionSelectionOptionOnDemandAccountIdentifier);
+               host_name = CFDictionaryGetValue(selectionOptions, kSCNetworkConnectionSelectionOptionOnDemandHostName);
+               skip_prefs = (isA_CFBoolean(no_user_prefs) && CFBooleanGetValue(no_user_prefs));
+
+               if (isA_CFBoolean(retry)) {
+                       is_retry = CFBooleanGetValue(retry);
                }
+       }
 
-           done_selection:
+       configuration = __SCNetworkConnectionCopyOnDemandConfiguration();
+
+       /* First, check for a match with the App Layer rules */
+       service_id = VPNAppLayerCopyMatchingService(connectionPrivate->client_audit_token,
+                                                   connectionPrivate->client_pid,
+                                                   connectionPrivate->client_uuid,
+                                                   connectionPrivate->client_bundle_id,
+                                                   host_name,
+                                                   account_identifier,
+                                                   &match_info);
+       if (service_id != NULL) {
+               Boolean use_app_layer   = TRUE;
+
+               if (isA_CFDictionary(configuration)) {
+                       found_trigger = __SCNetworkConnectionCopyTriggerWithService(configuration, service_id);
+                       if (found_trigger != NULL) {
+                               CFNumberRef status_num = CFDictionaryGetValue(found_trigger, kSCNetworkConnectionOnDemandStatus);
+                               if (isA_CFNumber(status_num)) {
+                                       CFNumberGetValue(status_num, kCFNumberIntType, &on_demand_status);
+                               }
+                               /*
+                                * If the trigger should be ignored, still use App Layer VPN if it is already connected or
+                                * is in the process of connecting.
+                                */
+                               if (__SCNetworkConnectionShouldIgnoreTrigger(found_trigger) &&
+                                   on_demand_status != kSCNetworkConnectionConnecting &&
+                                   on_demand_status != kSCNetworkConnectionConnected)
+                               {
+                                       use_app_layer = FALSE;
+                               }
+                       }
+               }
 
-               if (serviceNames)
-                       CFRelease(serviceNames);
-               if (services)
-                       CFRelease(services);
-               CFRelease(session);
+               if (use_app_layer) {
+                       /* If this is not the 'OnRetry' call, and the service has not yet started, the match may need to return false */
+                       if (!is_retry &&
+                           match_info != NULL &&
+                           on_demand_status != kSCNetworkConnectionConnecting &&
+                           on_demand_status != kSCNetworkConnectionConnected) {
+                               CFBooleanRef matchedOnRetry = CFDictionaryGetValue(match_info, kSCNetworkConnectionOnDemandMatchInfoOnRetry);
+                               if (matchedOnRetry && CFBooleanGetValue(matchedOnRetry)) {
+                                       /* Don't return that we matched always; wait for SCNetworkConnectionOnDemandShouldRetryOnFailure */
+                                       success = FALSE;
+                               }
+                       }
+                       connectionPrivate->type = kSCNetworkConnectionTypeAppLayerVPN;
+                       goto search_done;
+               } else {
+                       CFRelease(service_id);
+                       service_id = NULL;
+                       if (match_info != NULL) {
+                               CFRelease(match_info);
+                               match_info = NULL;
+                       }
+                       if (found_trigger != NULL) {
+                               CFRelease(found_trigger);
+                               found_trigger = NULL;
+                       }
+               }
+       }
 
-               if (debug > 1) {
-                       SCLog(TRUE, LOG_DEBUG, CFSTR("SCNetworkConnectionCopyUserPreferences %@"), success ? CFSTR("succeeded") : CFSTR("failed"));
-                       SCLog(TRUE, LOG_DEBUG, CFSTR("Selection options: %@"), selectionOptions);
+       /* Next, check the IP layer rules */
+       if (isA_CFDictionary(configuration) && host_name != NULL) {
+               Boolean triggerNow      = FALSE;
+
+               found_trigger = __SCNetworkConnectionCopyMatchingTriggerWithName(configuration, host_name, connectionPrivate->client_pid, is_retry, &match_info, &triggerNow, &requiredProbe);
+               if (found_trigger != NULL) {
+                       service_id = CFDictionaryGetValue(found_trigger, kSCNetworkConnectionOnDemandServiceID);
+                       if (isA_CFString(service_id)) {
+                               CFRetain(service_id);
+                               connectionPrivate->type = kSCNetworkConnectionTypeIPLayerVPN;
+                       } else {
+                               service_id = NULL;
+                       }
+                       if (!triggerNow) {
+                               success = FALSE;
+                       }
+                       goto search_done;
+               } else if (!is_retry) {
+                       goto search_done;
                }
 
-               return success;
+               if (match_info != NULL) {
+                       CFRelease(match_info);
+                       match_info = NULL;
+               }
        }
 
-       /* we don't have selection options */
+       /* Next, check the user preferences */
+       if (!skip_prefs && __SCNetworkConnectionCopyUserPreferencesInternal(selectionOptions, &service_id, &user_options)) {
+               CFMutableDictionaryRef  minfo;
+               CFNumberRef             type_num;
 
-       // (1) Figure out which service ID we care about, allocate it into passed "serviceID"
-       success = SCNetworkConnectionPrivateCopyDefaultServiceIDForDial(session, serviceID);
+               if (isA_CFDictionary(configuration)) {
+                       found_trigger = __SCNetworkConnectionCopyTriggerWithService(configuration, service_id);
+               }
+               connectionPrivate->type = kSCNetworkConnectionTypePPP;
+
+               minfo = CFDictionaryCreateMutable(NULL,
+                                                 0,
+                                                 &kCFTypeDictionaryKeyCallBacks,
+                                                 &kCFTypeDictionaryValueCallBacks);
+               type_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &connectionPrivate->type);
+               CFDictionarySetValue(minfo, kSCNetworkConnectionOnDemandMatchInfoVPNType, type_num);
+               CFRelease(type_num);
+               match_info = minfo;
+               goto search_done;
+       }
+
+search_done:
+       if (service_id == NULL) {
+               _SCErrorSet(kSCStatusOK);
+               success = FALSE;
+               goto done;
+       }
 
-       if (success && (*serviceID != NULL)) {
-               // (2) Get the list of user data for this service ID
-               CFPropertyListRef       userServices    = NULL;
+       connectionPrivate->service = _SCNetworkServiceCopyActive(NULL, service_id);
+       if (connectionPrivate->service == NULL) {
+               _SCErrorSet(kSCStatusOK);
+               success = FALSE;
+               goto done;
+       }
 
+       if (found_trigger != NULL) {
+               if (connectionPrivate->on_demand_info) {
+                     CFRelease(connectionPrivate->on_demand_info);
+               }
+               connectionPrivate->on_demand_info = found_trigger;
+               CFRetain(connectionPrivate->on_demand_info);
 
-               // (3) We are expecting an array if the user has defined records for this service ID or NULL if the user hasn't
-               if (userServices != NULL) {
-                       if (isA_CFArray(userServices)) {
-                               // (4) Get the default set of user options for this service
-                               success = SCNetworkConnectionPrivateCopyDefaultUserOptionsFromArray((CFArrayRef)userServices,
-                                                                                                   userOptions);
-                               if(success && (userOptions != NULL)) {
-                                       addPasswordFromKeychain(session, *serviceID, userOptions);
+               if (on_demand_status == kSCNetworkConnectionInvalid) {
+                       CFNumberRef status_num = CFDictionaryGetValue(found_trigger, kSCNetworkConnectionOnDemandStatus);
+                       if (isA_CFNumber(status_num)) {
+                               CFNumberGetValue(status_num, kCFNumberIntType, &on_demand_status);
+                       }
+               }
+
+               if (on_demand_status != kSCNetworkConnectionConnected) {
+                       if (connectionPrivate->type == kSCNetworkConnectionTypeAppLayerVPN) {
+                               /* Check App Layer on demand flag */
+                               CFBooleanRef app_on_demand_enabled =
+                                       CFDictionaryGetValue(found_trigger, kSCNetworkConnectionOnDemandMatchAppEnabled);
+                               if (isA_CFBoolean(app_on_demand_enabled) && CFBooleanGetValue(app_on_demand_enabled)) {
+                                       connectionPrivate->on_demand = TRUE;
                                }
                        } else {
-                               SCLog(TRUE, LOG_DEBUG, CFSTR("Error, userServices are not of type CFArray!"));
+                               connectionPrivate->on_demand = TRUE;
                        }
-
-                       CFRelease(userServices); // this is OK because SCNetworkConnectionPrivateISExpectedCFType() checks for NULL
                }
+       } else if (connectionPrivate->type == kSCNetworkConnectionTypePPP) {
+               /* If we got the service from __SCNetworkConnectionCopyUserPreferencesInternal, then it's on demand */
+               connectionPrivate->on_demand = TRUE;
        }
 
-       if (debug > 1) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("SCNetworkConnectionCopyUserPreferences %@, no selection options"), success ? CFSTR("succeeded") : CFSTR("failed"));
+       if (user_options == NULL) {
+               new_user_options = CFDictionaryCreateMutable(kCFAllocatorDefault,
+                                                            0,
+                                                            &kCFTypeDictionaryKeyCallBacks,
+                                                            &kCFTypeDictionaryValueCallBacks);
+       } else {
+               new_user_options = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, user_options);
+       }
+
+       if (host_name != NULL) {
+               CFDictionarySetValue(new_user_options, kSCNetworkConnectionSelectionOptionOnDemandHostName, host_name);
+       }
+
+       if (connectionPrivate->on_demand && match_info != NULL) {
+               CFDictionarySetValue(new_user_options, kSCNetworkConnectionSelectionOptionOnDemandMatchInfo, match_info);
+       }
+
+       connectionPrivate->on_demand_user_options = new_user_options;
+       CFRetain(connectionPrivate->on_demand_user_options);
+
+       if (requiredProbe) {
+               connectionPrivate->on_demand_required_probe = requiredProbe;
+               CFRetain(connectionPrivate->on_demand_required_probe);
+       }
+
+done:
+       if (service_id != NULL) {
+               CFRelease(service_id);
+       }
+
+       if (configuration != NULL) {
+               CFRelease(configuration);
+       }
+
+       if (found_trigger != NULL) {
+               CFRelease(found_trigger);
+       }
+
+       if (user_options != NULL) {
+               CFRelease(user_options);
+       }
+
+       if (new_user_options != NULL) {
+               CFRelease(new_user_options);
+       }
+
+       if (match_info != NULL) {
+               CFRelease(match_info);
+       }
+
+       if (requiredProbe != NULL) {
+               CFRelease(requiredProbe);
        }
 
-       CFRelease(session);
        return success;
 }
 
-
 //*******************************************************************************************
 // SCNetworkConnectionPrivateCopyDefaultServiceIDForDial
 // ----------------------------------------------------
@@ -2493,7 +4226,7 @@ SCNetworkConnectionCopyUserPreferences(CFDictionaryRef    selectionOptions,
 //     with the highest ordering
 //********************************************************************************************
 static Boolean
-SCNetworkConnectionPrivateCopyDefaultServiceIDForDial(SCDynamicStoreRef session, CFStringRef *serviceID)
+SCNetworkConnectionPrivateCopyDefaultServiceIDForDial(CFStringRef *serviceID)
 {
        Boolean                 foundService            = FALSE;
        CFPropertyListRef       lastServiceSelectedInIC = NULL;
@@ -2503,7 +4236,7 @@ SCNetworkConnectionPrivateCopyDefaultServiceIDForDial(SCDynamicStoreRef session,
        // we found the service the user last had open in IC
        if (lastServiceSelectedInIC != NULL) {
                // make sure its a PPP service
-               if (SCNetworkConnectionPrivateIsPPPService(session, lastServiceSelectedInIC, kSCValNetInterfaceSubTypePPPSerial, kSCValNetInterfaceSubTypePPPoE)) {
+               if (SCNetworkConnectionPrivateIsPPPService(lastServiceSelectedInIC, kSCValNetInterfaceSubTypePPPSerial, kSCValNetInterfaceSubTypePPPoE)) {
                        // make sure the service that we found is valid
                        CFDictionaryRef dict;
                        CFStringRef     key;
@@ -2512,7 +4245,7 @@ SCNetworkConnectionPrivateCopyDefaultServiceIDForDial(SCDynamicStoreRef session,
                                                                          kSCDynamicStoreDomainSetup,
                                                                          lastServiceSelectedInIC,
                                                                          kSCEntNetInterface);
-                       dict = SCDynamicStoreCopyValue(session, key);
+                       dict = SCDynamicStoreCopyValue(NULL, key);
                        CFRelease(key);
                        if (dict != NULL) {
                                CFRelease(dict);
@@ -2524,7 +4257,7 @@ SCNetworkConnectionPrivateCopyDefaultServiceIDForDial(SCDynamicStoreRef session,
        }
 
        if (!foundService) {
-               foundService = SCNetworkConnectionPrivateGetPPPServiceFromDynamicStore(session, serviceID);
+               foundService = SCNetworkConnectionPrivateGetPPPServiceFromDynamicStore(serviceID);
        }
 
        return foundService;
@@ -2536,7 +4269,7 @@ SCNetworkConnectionPrivateCopyDefaultServiceIDForDial(SCDynamicStoreRef session,
 // Find the highest ordered PPP service in the dynamic store
 //********************************************************************************
 static Boolean
-SCNetworkConnectionPrivateGetPPPServiceFromDynamicStore(SCDynamicStoreRef session, CFStringRef *serviceID)
+SCNetworkConnectionPrivateGetPPPServiceFromDynamicStore(CFStringRef *serviceID)
 {
        CFDictionaryRef dict            = NULL;
        CFStringRef     key             = NULL;
@@ -2555,7 +4288,7 @@ SCNetworkConnectionPrivateGetPPPServiceFromDynamicStore(SCDynamicStoreRef sessio
                        break;
                }
 
-               dict = SCDynamicStoreCopyValue(session, key);
+               dict = SCDynamicStoreCopyValue(NULL, key);
                if (!isA_CFDictionary(dict)) {
                        fprintf(stderr, "no global IPv4 entity\n");
                        break;
@@ -2571,7 +4304,7 @@ SCNetworkConnectionPrivateGetPPPServiceFromDynamicStore(SCDynamicStoreRef sessio
                for (i = 0; i < count; i++) {
                        CFStringRef service = CFArrayGetValueAtIndex(serviceIDs, i);
 
-                       if (SCNetworkConnectionPrivateIsPPPService(session, service, kSCValNetInterfaceSubTypePPPSerial, kSCValNetInterfaceSubTypePPPoE)) {
+                       if (SCNetworkConnectionPrivateIsPPPService(service, kSCValNetInterfaceSubTypePPPSerial, kSCValNetInterfaceSubTypePPPoE)) {
                                *serviceID = CFRetain(service);
                                success = TRUE;
                                break;
@@ -2625,7 +4358,7 @@ SCNetworkConnectionPrivateCopyDefaultUserOptionsFromArray(CFArrayRef userOptions
 // Check and see if the service is a PPP service of the given types
 //********************************************************************************
 static Boolean
-SCNetworkConnectionPrivateIsPPPService(SCDynamicStoreRef session, CFStringRef serviceID, CFStringRef subType1, CFStringRef subType2)
+SCNetworkConnectionPrivateIsPPPService(CFStringRef serviceID, CFStringRef subType1, CFStringRef subType2)
 {
        CFStringRef     entityKey;
        Boolean         isPPPService            = FALSE;
@@ -2640,7 +4373,7 @@ SCNetworkConnectionPrivateIsPPPService(SCDynamicStoreRef session, CFStringRef se
                return FALSE;
        }
 
-       serviceDict = SCDynamicStoreCopyValue(session, entityKey);
+       serviceDict = SCDynamicStoreCopyValue(NULL, entityKey);
        if (serviceDict != NULL) {
                if (isA_CFDictionary(serviceDict)) {
                        CFStringRef     type;
@@ -2672,7 +4405,7 @@ SCNetworkConnectionPrivateIsPPPService(SCDynamicStoreRef session, CFStringRef se
 // them to the PPP and IPSec dictionaries
 //********************************************************************************
 static void
-addPasswordFromKeychain(SCDynamicStoreRef session, CFStringRef serviceID, CFDictionaryRef *userOptions)
+addPasswordFromKeychain(CFStringRef serviceID, CFDictionaryRef *userOptions)
 {
        CFPropertyListRef       uniqueID;
        CFStringRef             password;
@@ -2691,7 +4424,7 @@ addPasswordFromKeychain(SCDynamicStoreRef session, CFStringRef serviceID, CFDict
        password = copyPasswordFromKeychain(uniqueID);
 
        /* then, if necessary, get the IPSec Shared Secret */
-       if (SCNetworkConnectionPrivateIsPPPService(session, serviceID, kSCValNetInterfaceSubTypeL2TP, 0)) {
+       if (SCNetworkConnectionPrivateIsPPPService(serviceID, kSCValNetInterfaceSubTypeL2TP, 0)) {
                CFMutableStringRef      uniqueIDSS;
 
                uniqueIDSS = CFStringCreateMutableCopy(NULL, 0, uniqueID);
@@ -2839,3 +4572,25 @@ copyPasswordFromKeychain(CFStringRef uniqueID)
        return NULL;
 #endif // !TARGET_OS_IPHONE
 }
+
+
+__private_extern__
+char *
+__SCNetworkConnectionGetControllerPortName()
+{
+#if    ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 70000)) && !TARGET_IPHONE_SIMULATOR
+       if (scnc_server_name == NULL){
+               if (!(sandbox_check(getpid(), "mach-lookup", SANDBOX_FILTER_GLOBAL_NAME | SANDBOX_CHECK_NO_REPORT, PPPCONTROLLER_SERVER_PRIV))){
+                       scnc_server_name = PPPCONTROLLER_SERVER_PRIV;
+               }
+               else{
+                       scnc_server_name = PPPCONTROLLER_SERVER;
+               }
+               SCLog(TRUE, LOG_DEBUG, CFSTR("__SCNetworkConnectionGetControllerPortName() returns port: %s"), scnc_server_name);
+       }
+#else
+       scnc_server_name = PPPCONTROLLER_SERVER;
+#endif
+       return scnc_server_name;
+}
+
diff --git a/SystemConfiguration.fproj/SCNetworkConnectionInternal.h b/SystemConfiguration.fproj/SCNetworkConnectionInternal.h
new file mode 100644 (file)
index 0000000..9bef13b
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2012, 2013 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@
+ */
+
+#ifndef _SCNETWORKCONNECTIONINTERNAL_H
+#define _SCNETWORKCONNECTIONINTERNAL_H
+
+#include <sys/cdefs.h>
+
+
+__BEGIN_DECLS
+
+void           __SCNetworkConnectionForceOnDemandConfigurationRefresh(void);
+char *         __SCNetworkConnectionGetControllerPortName(void);
+CFDictionaryRef        __SCNetworkConnectionCopyTokenParameters(SCNetworkConnectionRef connection);
+
+__END_DECLS
+
+#endif /* _SCNETWORKCONNECTIONINTERNAL_H */
index 6e98de14f609251d79db55e239580df3e6d96ac3..7b58f62526f1ee6228f2321b0823c450e631b9fa 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2006-2012 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -399,6 +399,7 @@ processPreferences(CFStringRef                      serviceID,
                CFDictionaryRef dict;
 
                dict = CFArrayGetValueAtIndex(prefs, i);
+               assert(dict != NULL);
                if (isA_CFDictionary(dict)) {
                        newDict = (*callout)(serviceID, dict, context1, context2, context3);
                        if (newDict == NULL) {
@@ -2179,6 +2180,7 @@ SCUserPreferencesSetInterfacePassword(SCUserPreferencesRef                userPreferences,
                                                                              &kCFTypeDictionaryKeyCallBacks,
                                                                              &kCFTypeDictionaryValueCallBacks);
                                }
+                               assert(newConfig != NULL);
                                CFDictionarySetValue(newConfig,
                                                     kSCPropNetVPNAuthPassword,
                                                     unique_id);
index d790dbb69223bf73e495b54114c94cd7ba98546e..81e6194a6473df31b342354f8343492bb68d32de 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2008, 2009, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2006, 2008, 2009, 2011-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -40,7 +40,6 @@ __BEGIN_DECLS
 #pragma mark -
 #pragma mark SCNetworkConnection SPIs
 
-
 CFArrayRef /* of SCNetworkServiceRef's */
 SCNetworkConnectionCopyAvailableServices       (SCNetworkSetRef                set)                    __OSX_AVAILABLE_STARTING(__MAC_10_5,__IPHONE_2_0);
 
@@ -68,6 +67,9 @@ SCNetworkConnectionSuspend                    (SCNetworkConnectionRef         connection)             __OSX_AVAILAB
 Boolean
 SCNetworkConnectionResume                      (SCNetworkConnectionRef         connection)             __OSX_AVAILABLE_STARTING(__MAC_10_3,__IPHONE_2_0);
 
+Boolean
+SCNetworkConnectionRefreshOnDemandState                (SCNetworkConnectionRef         connection)             __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
+
 Boolean
 SCNetworkConnectionSetClientInfo               (SCNetworkConnectionRef         connection,
                                                 mach_port_t                    client_audit_session,
@@ -75,6 +77,280 @@ SCNetworkConnectionSetClientInfo            (SCNetworkConnectionRef         connection,
                                                 gid_t                          client_gid,
                                                 pid_t                          client_pid)             __OSX_AVAILABLE_STARTING(__MAC_10_8,__IPHONE_5_0);
 
+/*!
+ @function SCNetworkConnectionCreate
+ @discussion Create a network connection that is not associated with any
+     network service.
+ @param allocator The CFAllocator that should be used to allocate
+     memory for the connection structure.  This parameter may be
+     NULL in which case the current default CFAllocator is used.
+     If this reference is not a valid CFAllocator, the behavior
+     is undefined.
+ @param callout The function to be called when the status
+     of the connection changes.  If this parameter is NULL, the
+     application will not receive notifications of status change
+     and will need to poll for updates.
+ @param context The SCNetworkConnectionContext associated with the
+     callout.
+ @return The new SCNetworkConnection object.
+ */
+SCNetworkConnectionRef
+SCNetworkConnectionCreate                      (CFAllocatorRef                 allocator,
+                                                SCNetworkConnectionCallBack    callout,
+                                                SCNetworkConnectionContext     *context)               __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
+
+/*!
+ @function SCNetworkConnectionSetClientAuditInfo
+ @discussion Set audit information for the process that is initiating the network traffic
+      that will be transmitted over this network connection.
+ @param connection The SCNetworkConnection object.
+ @param client_audit_token The audit token of the initiator process.
+ @param audit_session The audit session mach port of the initiator process.
+ @param bootstrap_port The bootstrap port of the initiator process.
+ @param pid The PID of the initiator process.
+ @param uuid The Mach-O UUID of the initiator process.
+ @param bundle_id The CFBundleIdentifier of the initiator process.
+ @return TRUE if the audit token was set successfully, FALSE if an error occurred.
+ */
+Boolean
+SCNetworkConnectionSetClientAuditInfo          (SCNetworkConnectionRef         connection,
+                                                audit_token_t                  client_audit_token,
+                                                mach_port_t                    audit_session,
+                                                mach_port_t                    bootstrap_port,
+                                                pid_t                          pid,
+                                                const uuid_t                   uuid,
+                                                const char                     *bundle_id)             __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
+
+/*!
+ @defined kSCNetworkConnectionSelectionOptionNoUserPrefs
+ @abstract Indicates whether or not SCNetworkConnectionSelectServiceWithOptions
+     should consult the user preferences to find a network service.
+ */
+#define kSCNetworkConnectionSelectionOptionNoUserPrefs         CFSTR("NoUserPrefs")    /* CFBoolean */
+
+/*!
+ @define kSCNetworkConnectionSelectionOptionOnDemandTrafficClass
+ @abstract The traffic class that is attempting to trigger OnDemand.
+ */
+#define kSCNetworkConnectionSelectionOptionOnDemandTrafficClass        CFSTR("OnDemandTrafficClass")   // CFNumber
+                                                                                               // __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/)
+/*!
+ @define kSCNetworkConnectionSelectionOptionOnDemandAccountIdentifier
+ @abstract The account identifier that is attempting to trigger OnDemand.
+ */
+#define kSCNetworkConnectionSelectionOptionOnDemandAccountIdentifier   CFSTR("OnDemandAccountIdentifier")      /* CFString */
+
+/*!
+ @define kSCNetworkConnectionSelectionOptionOnDemandMatchInfo
+ @abstract A dictionary containing information about the On Demand trigger that matched
+ */
+#define kSCNetworkConnectionSelectionOptionOnDemandMatchInfo   CFSTR("OnDemandMatchInfo")      /* CFDictionary */
+
+/*!
+ @define kSCNetworkConnectionOnDemandMatchInfoVPNType
+ @abstract The type of VPN connection associated with the matching trigger.
+ */
+#define kSCNetworkConnectionOnDemandMatchInfoVPNType           CFSTR("OnDemandMatchInfoVPNType")       /* CFNumber containing a SCNetworkConnectionType */
+
+/*!
+ @define kSCNetworkConnectionOnDemandMatchInfoDomain
+ @abstract The specific DNS domain in the trigger's match domains that matched the on demand hostname.
+ */
+#define kSCNetworkConnectionOnDemandMatchInfoDomain            CFSTR("OnDemandMatchInfoDomain")        /* CFString */
+
+/*!
+ @define kSCNetworkConnectionOnDemandMatchInfoAppRuleID
+ @abstract The identifier of the app rule in the matching trigger that matched the calling app.
+ */
+#define kSCNetworkConnectionOnDemandMatchInfoAppRuleID         CFSTR("OnDemandMatchInfoAppRuleID")     /* CFString */
+
+/*
+ @define kSCNetworkConnectionOnDemandMatchInfoOnRetry
+ @abstract A flag indicating if the on demand hostname matched a domain in the "on retry" match domains.
+ */
+#define kSCNetworkConnectionOnDemandMatchInfoOnRetry           CFSTR("OnDemandMatchInfoOnRetry")       /* CFString */
+
+
+/*!
+ @function SCNetworkConnectionSelectServiceWithOptions
+ @discussion Associate a network connection with a network service based on some
+      selection options. This function can only be called on connections that are
+      not already associated with a network service.
+ @param connection The SCNetworkConnection object.
+ @param selectionOptions A dictionary containing some options to be used to
+      select the appropriate service.
+ @return TRUE if an appropriate network service was found and was associated with
+      the connection, FALSE otherwise.
+ */
+Boolean
+SCNetworkConnectionSelectServiceWithOptions    (SCNetworkConnectionRef         connection,
+                                                CFDictionaryRef                selectionOptions)       __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
+
+/*!
+ @function SCNetworkConnectionOnDemandShouldRetryOnFailure
+ @discussion After SCNetworkConnectionSelectServiceWithOptions returns FALSE, use
+       this function to determine if an On Demand service was indeed matched for
+       On Retry behavior (try resolving/connecting, and start VPN on failure).
+ @param connection The SCNetworkConnection object.
+ @return TRUE if the selected On Demand connection should be retried on DNS or connection
+       failure, FALSE otherwise.
+ */
+Boolean
+SCNetworkConnectionOnDemandShouldRetryOnFailure        (SCNetworkConnectionRef         connection)             __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
+
+/*!
+ @function SCNetworkConnectionCanTunnelAddress
+ @discussion This function should be called on a connection object selected with
+       SCNetworkConnectionSelectServiceWithOptions. If the address belongs to
+       the connection (the tunnel can be used for the address), the function
+       will return TRUE. If startImmediately is set, the address should not be trusted
+       and the VPN should be brought up before attempting to connect.
+ @param connection The SCNetworkConnection object.
+ @param address The address structure to check.
+ @param startImmediately On return, TRUE indicates that the address is not trusted
+       and the VPN should be started immediately.
+ @return TRUE if the selected VPN connection's tunnel routes match the address.
+ */
+Boolean
+SCNetworkConnectionCanTunnelAddress            (SCNetworkConnectionRef         connection,
+                                                const struct sockaddr          *address,
+                                                Boolean                        *startImmediately)      __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
+
+/*!
+ @function SCNetworkConnectionIsOnDemandSuspended
+ @discussion Indicates whether the On Demand connection is suspended or not. Call
+       SCNetworkConnectionSelectServiceWithOptions before calling this function.
+ @param connection The SCNetworkConnection object.
+ @return TRUE if the On Demand connection is suspended, FALSE otherwise.
+ */
+Boolean
+SCNetworkConnectionIsOnDemandSuspended         (SCNetworkConnectionRef         connection)             __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
+
+/*!
+ @function SCNetworkConnectionCopyOnDemandInfo
+ @discussion Indicates whether or not the caller should start the network connection,
+      assuming that the caller has network traffic that needs to use the network connection.
+ @param connection The SCNetworkConnection object.
+ @param onDemandRemoteAddress On return, contains the address of the server providing the
+      network connection. Ownership follows the "Create" rule.
+ @param onDemandConnectionStatus On return, contains the current status of the network
+      connection.
+ @return TRUE if the caller should start the connection upon traffic demand, FALSE otherwise.
+ */
+Boolean
+SCNetworkConnectionCopyOnDemandInfo            (SCNetworkConnectionRef         connection,
+                                                CFStringRef                    *onDemandRemoteAddress,
+                                                SCNetworkConnectionStatus      *onDemandConnectionStatus)      __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
+
+/*!
+ @function SCNetworkConnectionTriggerOnDemandIfNeeded
+ @discussion Trigger a VPN On Demand connection based on a hostname. This function combines the
+       functionality of calling SCNetworkConnectionCreate, SCNetworkConnectionSelectServiceWithOptions,
+       and SCNetworkConnectionStart. The function blocks until the connection is established,
+       fails, or the timer runs out. Since it blocks, this function should not generally be called on
+       the main runloop. NOTE: This function should only be called from process running
+       in the user's context to ensure that the user's keychain is available.
+ @param hostName The hostname that needs to be resolved and accessed.
+ @param afterDNSFail Pass FALSE if this call is made before trying to resolve the hostname, and
+       TRUE if the hostname resolution already failed.
+ @param timeout Number of seconds to wait for a connection. Passing 0 sets a timeout of forever.
+ @param trafficClass Numeric value of a traffic class. Pass 0 for default traffic class, 'Best Effort'.
+ @return TRUE if the connection was established or was not needed, FALSE otherwise.
+ */
+Boolean
+SCNetworkConnectionTriggerOnDemandIfNeeded     (CFStringRef                    hostName,
+                                                Boolean                        afterDNSFail,
+                                                int                            timeout,
+                                                int                            trafficClass)                   __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
+
+/*!
+ @function SCNetworkConnectionGetReachabilityInfo
+ @discussion Get the reachability info of the connection server.
+ @param connection The SCNetworkConnection object.
+ @param reach_flags On return, contains the reachability flags of the connection server.
+ @param reach_if_index On return, contains the index of the interface through which
+      the connection server is reachable.
+ @return TRUE if the reachability information was available for the connection
+      server, FALSE otherwise.
+ */
+Boolean
+SCNetworkConnectionGetReachabilityInfo         (SCNetworkConnectionRef         connection,
+                                                SCNetworkReachabilityFlags     *reach_flags,
+                                                unsigned int                   *reach_if_index)        __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
+
+
+/*!
+ @enum SCNetworkConnectionType
+ @discussion Type of the network connection.
+ @constant kSCNetworkConnectionTypeUnknown
+     The type of the network connection has not yet been determined.
+ @constant kSCNetworkConnectionTypePPP
+     The network connection is a Point To Point Protocol connection.
+ @constant kSCNetworkConnectionTypeIPLayerVPN
+     The network connection is a IP-layer Virtual Private Network connection.
+ @constant kSCNetworkConnectionTypeAppLayerVPN
+     The network connection is an Application-layer Virtual Private Network connection.
+ */
+enum {
+       kSCNetworkConnectionTypeUnknown         = 0,
+       kSCNetworkConnectionTypePPP             = 1,
+       kSCNetworkConnectionTypeIPLayerVPN      = 2,
+       kSCNetworkConnectionTypeAppLayerVPN     = 3,
+};
+
+typedef int SCNetworkConnectionType;
+
+/*!
+ @function SCNetworkConnectionGetType
+ @discussion Get the type of the network connection.
+ @param connection The SCNetworkConnection object.
+ @return The type of the network connection.
+ */
+SCNetworkConnectionType
+SCNetworkConnectionGetType                     (SCNetworkConnectionRef         connection)             __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
+
+/*!
+ @defined kSCNetworkConnectionFlowPropertyHostName
+ @abstract The host name of the flow's destination server.
+ */
+#define kSCNetworkConnectionFlowPropertyHostName       CFSTR("HostName")       /* CFString */
+
+/*!
+ @defined kSCNetworkConnectionFlowPropertyHostAddress
+ @abstract The address of the flow's destination server.
+ */
+#define kSCNetworkConnectionFlowPropertyHostAddress    CFSTR("HostAddress")    /* CFData containing a struct sockaddr */
+
+/*!
+ @defined kSCNetworkConnectionFlowPropertyHostPort
+ @abstract The port of the flow's destination server.
+ */
+#define kSCNetworkConnectionFlowPropertyHostPort       CFSTR("HostPort")       /* CFNumber */
+
+/*!
+ @function SCNetworkConnectionCopyFlowDivertToken
+ @discussion Copy a token that should be used to activate flow divert on
+      a socket, causing data on the socket to be diverted through the
+      Application-layer VPN provided by the given network connection.
+ @param connection The SCNetworkConnection object.
+ @param flowProperties A dictionary containing properties of the socket
+      to be diverted.
+ @return The flow divert token, or NULL if the flow properties are not valid
+      or the connection does not provide Application-Layer VPN services.
+ */
+CFDataRef
+SCNetworkConnectionCopyFlowDivertToken         (SCNetworkConnectionRef         connection,
+                                                CFDictionaryRef                flowProperties)         __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
+
+#define kSCNetworkConnectionAppPropertyRuleID          CFSTR("RuleID")
+#define kSCNetworkConnectionAppPropertyCodeDirHash     CFSTR("CodeDirHash")
+#define kSCNetworkConnectionAppPropertySigningID       CFSTR("SigningID")
+#define kSCNetworkConnectionAppPropertyAuditToken      CFSTR("AuditToken")
+#define kSCNetworkConnectionAppPropertyPID             CFSTR("ProcessID")
+#define kSCNetworkConnectionAppPropertyUUID            CFSTR("UUID")
+
+int
+SCNetworkConnectionGetServiceIdentifier                (SCNetworkConnectionRef         connection)             __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
 
 #pragma mark -
 #pragma mark SCNetworkConnection "VPN on Demand" SPIs
@@ -107,6 +383,8 @@ SCNetworkConnectionSetClientInfo            (SCNetworkConnectionRef         connection,
  *         <array>
  *           <string>external.mycompany.com</string>
  *         </array>
+ *         <key>OnDemandMatchAppEnabled</key>
+ *         <integer>0</integer>
  *       </dict>
  *     </array>
  *   </dict>
@@ -115,34 +393,88 @@ SCNetworkConnectionSetClientInfo          (SCNetworkConnectionRef         connection,
 // notify(3) key
 #define kSCNETWORKCONNECTION_ONDEMAND_NOTIFY_KEY               "com.apple.system.SCNetworkConnectionOnDemand"
 
+// SCNetworkConnection status
+// (included in the dictionary returned by SCNetworkConnectionCopyExtendedStatus)
+#define kSCNetworkConnectionStatus                             CFSTR("Status")                 /* CFNumber */
+
 // a CFArray[CFDictionary] of VPN on Demand "trigger" configurations
-#define kSCNetworkConnectionOnDemandTriggers                   CFSTR("Triggers")
+#define kSCNetworkConnectionOnDemandTriggers                   CFSTR("Triggers")               /* CFArray[CFDictionary] */
 
 // VPN service ID
-#define kSCNetworkConnectionOnDemandServiceID                  CFSTR("ServiceID")
+#define kSCNetworkConnectionOnDemandServiceID                  CFSTR("ServiceID")              /* CFString */
 
 // VPN service status (idle, connecting, connected, disconnecting)
-#define kSCNetworkConnectionOnDemandStatus                     CFSTR("Status")
+#define kSCNetworkConnectionOnDemandStatus                     CFSTR("Status")                 /* CFNumber */
 
 // VPN server address
-#define kSCNetworkConnectionOnDemandRemoteAddress              CFSTR("RemoteAddress")
+#define kSCNetworkConnectionOnDemandRemoteAddress              CFSTR("RemoteAddress")          /* CFString */
+
+// Reachability flags for the VPN server
+#define kSCNetworkConnectionOnDemandReachFlags                 CFSTR("ReachFlags")             /* CFNumber */
+
+// Reachability interface index for the VPN server
+#define kSCNetworkConnectionOnDemandReachInterfaceIndex                CFSTR("ReachInterfaceIndex")    /* CFNumber */
+
+// Network detection has detected DNS Redirecting (like OpenDNS)
+#define kSCNetworkConnectionOnDemandDNSRedirectDetected                CFSTR("DNSRedirectDetected")    /* CFBoolean */
+
+// a dictionary of address information for known lying results
+#define kSCNetworkConnectionOnDemandDNSRedirectedAddresses     CFSTR("DNSRedirectedAddresses") /* CFDictionary[CFDictionary] */
+
+// A dictionary of routes tunneled over this service in the past
+#define kSCNetworkConnectionOnDemandTunneledNetworks           CFSTR("TunneledNetworks")       /* CFDictionary[CFDictionary] */
+
+// An array of plugin PIDs
+#define kSCNetworkConnectionOnDemandPluginPIDs                 CFSTR("PluginPIDs")             /* CFArray[CFNumber] */
+
+// A dictionary of results, keyed by probe string
+#define kSCNetworkConnectionOnDemandProbeResults               CFSTR("ProbeResults")           /* CFDictionary[CFBoolean] */
+
+/* The following generic NetworkInfo keys are currently used in the dynamic store as follows:
+
+ kSCNetworkConnectionOnDemandTunneledNetworks (CFDictionary)
+       - kSCNetworkConnectionNetworkInfoIPv4 (CFDictionary)
+               - kSCNetworkConnectionNetworkInfoIncludedRoutes (CFDictionary)
+                       - kSCNetworkConnectionNetworkInfoAddresses (CFData)
+                       - kSCNetworkConnectionNetworkInfoMasks (CFData)
+               - kSCNetworkConnectionNetworkInfoExcludedRoutes (CFDictionary)
+                       - kSCNetworkConnectionNetworkInfoAddresses (CFData)
+                       - kSCNetworkConnectionNetworkInfoMasks (CFData)
+       - kSCNetworkConnectionNetworkInfoIPv6 (CFDictionary)
+               [Same as for IPv4]
+
+ kSCNetworkConnectionOnDemandDNSRedirectedAddresses (CFDictionary)
+       - kSCNetworkConnectionNetworkInfoIPv4 (CFDictionary)
+               - kSCNetworkConnectionNetworkInfoAddresses (CFData)
+       - kSCNetworkConnectionNetworkInfoIPv6 (CFDictionary)
+               - kSCNetworkConnectionNetworkInfoAddresses (CFData)
+ */
+#define kSCNetworkConnectionNetworkInfoIPv4                    CFSTR("IPv4")                   /* CFDictionary[CFType] */
+#define kSCNetworkConnectionNetworkInfoIPv6                    CFSTR("IPv6")                   /* CFDictionary[CFType] */
+#define kSCNetworkConnectionNetworkInfoIncludedRoutes          CFSTR("IncludedRoutes")         /* CFDictionary[CFData] */
+#define kSCNetworkConnectionNetworkInfoExcludedRoutes          CFSTR("ExcludedRoutes")         /* CFDictionary[CFData] */
+#define kSCNetworkConnectionNetworkInfoAddresses               CFSTR("Addresses")              /* CFData */
+#define kSCNetworkConnectionNetworkInfoMasks                   CFSTR("Masks")                  /* CFData */
 
 // a CFArray[CFString] representing those domain (or host) names that, if
 // matched to a target hostname, should result in our first establishing
 // the VPN connection before any DNS queries are issued.
-#define kSCNetworkConnectionOnDemandMatchDomainsAlways         CFSTR("OnDemandMatchDomainsAlways")
+#define kSCNetworkConnectionOnDemandMatchDomainsAlways         CFSTR("OnDemandMatchDomainsAlways")     /* CFArray[CFString] */
 
 // a CFArray[CFString] representing those domain (or host) names that, if
 // matched to a target hostname, should result in a DNS query regardless of
 // whether the VPN connection has been established.  If the DNS query returns
 // an [EAI_NONAME] error then we should establish the VPN connection and
 // re-issue / retry the query.
-#define kSCNetworkConnectionOnDemandMatchDomainsOnRetry                CFSTR("OnDemandMatchDomainsOnRetry")
+#define kSCNetworkConnectionOnDemandMatchDomainsOnRetry                CFSTR("OnDemandMatchDomainsOnRetry")    /* CFArray[CFString] */
 
 // a CFArray[CFString] representing those domain (or host) names that should
 // be excluded from those that would be used to establish tje VPN connection.
-#define kSCNetworkConnectionOnDemandMatchDomainsNever          CFSTR("OnDemandMatchDomainsNever")
+#define kSCNetworkConnectionOnDemandMatchDomainsNever          CFSTR("OnDemandMatchDomainsNever")      /* CFArray[CFString] */
 
+// A CFNumber (0 or 1) indicating whether or not the App Layer rules should be
+// used to decide whether or not to establish the tunnel connection.
+#define kSCNetworkConnectionOnDemandMatchAppEnabled            CFSTR("OnDemandMatchAppEnabled")        /* CFNumber */
 
 Boolean
 __SCNetworkConnectionCopyOnDemandInfoWithName  (SCDynamicStoreRef              *storeP,
index bb681bd6faea74dafd56cc1aab479eb1b56f75d4..b66bcb79710ccec64dfd2ca149b584a3c6722cf0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2012 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -63,7 +63,9 @@
 #include <IOKit/network/IOEthernetInterface.h> // for kIOEthernetInterfaceClass
 #include <IOKit/serial/IOSerialKeys.h>
 #include <IOKit/storage/IOStorageDeviceCharacteristics.h>
+#if    !TARGET_IPHONE_SIMULATOR
 #include <IOKit/usb/USB.h>
+#endif // !TARGET_IPHONE_SIMULATOR
 
 #include "dy_framework.h"
 
 #define kPCIThunderboltString          "PCI-Thunderbolt"
 #endif
 
-#ifndef        kUSBProductString
-#define kUSBProductString              "USB Product Name"
-#endif
-
 #ifndef        kIOUserEthernetInterfaceRoleKey
 #define        kIOUserEthernetInterfaceRoleKey "InterfaceRole"
 #endif
@@ -123,6 +121,7 @@ enum {
        kSortBluetoothPAN_GN,
        kSortBluetoothPAN_NAP,
        kSortBluetoothPAN_U,
+       kSortThunderbolt,
        kSortBond,
        kSortBridge,
        kSortVLAN,
@@ -180,12 +179,13 @@ static SCNetworkInterfacePrivate __kSCNetworkInterfaceIPv4        = {
        0,                                      // entryID
        NULL,                                   // overrides
        FALSE,                                  // modemIsV92
+       NULL,                                   // name prefix
        NULL,                                   // type
        NULL,                                   // unit
        { NULL, 0, 0 },                         // usb { name, vid, pid }
        kSortUnknown,                           // sort_order
        FALSE,                                  // supportsBond
-       { NULL, NULL, NULL },                   // bond { interfaces, options, mode }
+       { NULL, NULL, NULL },                   // bond { interfaces, mode, options }
        FALSE,                                  // supportsBridge
        { NULL, NULL },                         // bridge { interfaces, options }
        FALSE,                                  // supportsVLAN
@@ -223,12 +223,13 @@ static SCNetworkInterfacePrivate __kSCNetworkInterfaceLoopback    = {
        0,                                      // entryID
        NULL,                                   // overrides
        FALSE,                                  // modemIsV92
+       NULL,                                   // name prefix
        NULL,                                   // type
        NULL,                                   // unit
        { NULL, 0, 0 },                         // usb { name, vid, pid }
        kSortUnknown,                           // sort_order
        FALSE,                                  // supportsBond
-       { NULL, NULL, NULL },                   // bond { interfaces, options, mode }
+       { NULL, NULL, NULL },                   // bond { interfaces, mode, options }
        FALSE,                                  // supportsBridge
        { NULL, NULL },                         // bridge { interfaces, options }
        FALSE,                                  // supportsVLAN
@@ -392,11 +393,11 @@ __SCNetworkInterfaceCopyDescription(CFTypeRef cf)
                CFStringAppendFormat(result, NULL, CFSTR(", unit = %@"), interfacePrivate->unit);
        }
        if ((interfacePrivate->usb.vid != NULL) || (interfacePrivate->usb.pid != NULL)) {
-               int     pid;
-               int     vid;
+               int     pid     = 0;
+               int     vid     = 0;
 
                if (!isA_CFNumber(interfacePrivate->usb.pid) ||
-                   !CFNumberGetValue(interfacePrivate->usb.vid, kCFNumberIntType, &pid)) {
+                   !CFNumberGetValue(interfacePrivate->usb.pid, kCFNumberIntType, &pid)) {
                        pid = 0;
                }
                if (!isA_CFNumber(interfacePrivate->usb.vid) ||
@@ -410,8 +411,8 @@ __SCNetworkInterfaceCopyDescription(CFTypeRef cf)
                }
 
                CFStringAppendFormat(result, NULL, CFSTR(", USB vid/pid = 0x%0x/0x%0x"),
-                                    interfacePrivate->usb.vid,
-                                    interfacePrivate->usb.pid);
+                                    vid,
+                                    pid);
        }
        if (interfacePrivate->configurationAction != NULL) {
                CFStringAppendFormat(result, NULL, CFSTR(", action = %@"), interfacePrivate->configurationAction);
@@ -444,7 +445,7 @@ __SCNetworkInterfaceCopyDescription(CFTypeRef cf)
                        member = CFArrayGetValueAtIndex(interfacePrivate->bond.interfaces, i);
                        CFStringAppendFormat(result, NULL,
                                             CFSTR("%s%@"),
-                                            (i == 0) ? ", interfaces = " : ", ",
+                                            (i == 0) ? ", interfaces = " : ",",
                                             SCNetworkInterfaceGetBSDName(member));
                }
        }
@@ -466,7 +467,7 @@ __SCNetworkInterfaceCopyDescription(CFTypeRef cf)
                        member = CFArrayGetValueAtIndex(interfacePrivate->bridge.interfaces, i);
                        CFStringAppendFormat(result, NULL,
                                             CFSTR("%s%@"),
-                                            (i == 0) ? ", interfaces = " : ", ",
+                                            (i == 0) ? ", interfaces = " : ",",
                                             SCNetworkInterfaceGetBSDName(member));
                }
        }
@@ -556,6 +557,9 @@ __SCNetworkInterfaceDeallocate(CFTypeRef cf)
        if (interfacePrivate->overrides != NULL)
                CFRelease(interfacePrivate->overrides);
 
+       if (interfacePrivate->prefix != NULL)
+               CFRelease(interfacePrivate->prefix);
+
        if (interfacePrivate->type != NULL)
                CFRelease(interfacePrivate->type);
 
@@ -712,7 +716,7 @@ __SCNetworkInterfaceInitialize(void)
 
        // get mach port used to communication with IOKit
        kr = IOMasterPort(MACH_PORT_NULL, &masterPort);
-       if (kr != KERN_SUCCESS) {
+       if (kr != kIOReturnSuccess) {
                SCLog(TRUE, LOG_DEBUG,
                      CFSTR("__SCNetworkInterfaceInitialize(), could not get IOMasterPort, kr = 0x%x"),
                      kr);
@@ -772,6 +776,7 @@ __SCNetworkInterfaceCreatePrivate(CFAllocatorRef    allocator,
        interfacePrivate->entryID                       = 0;
        interfacePrivate->overrides                     = NULL;
        interfacePrivate->modemIsV92                    = FALSE;
+       interfacePrivate->prefix                        = NULL;
        interfacePrivate->type                          = NULL;
        interfacePrivate->unit                          = NULL;
        interfacePrivate->usb.name                      = NULL;
@@ -1166,6 +1171,34 @@ IOCopyCFStringValue(CFTypeRef ioVal)
 }
 
 
+static CFStringRef
+IODictionaryCopyBSDName(CFDictionaryRef io_dict)
+{
+       CFStringRef     if_bsdName;
+       CFStringRef     if_prefix;
+       CFNumberRef     if_unit;
+
+       if_bsdName = CFDictionaryGetValue(io_dict, CFSTR(kIOBSDNameKey));
+       if (if_bsdName != NULL) {
+               return IOCopyCFStringValue(if_bsdName);
+       }
+
+       // no BSD name, get interface prefix and unit
+       if_prefix = CFDictionaryGetValue(io_dict, CFSTR(kIOInterfaceNamePrefix));
+       if_unit   = CFDictionaryGetValue(io_dict, CFSTR(kIOInterfaceUnit));
+       if (isA_CFString(if_prefix) && isA_CFNumber(if_unit)) {
+               // if both prefix and unit available, construct BSD name
+               if_bsdName = CFStringCreateWithFormat(NULL,
+                                                     NULL,
+                                                     CFSTR("%@%@"),
+                                                     if_prefix,
+                                                     if_unit);
+       }
+
+       return if_bsdName;
+};
+
+
 static CFStringRef
 IODictionaryCopyCFStringValue(CFDictionaryRef io_dict, CFStringRef io_key)
 {
@@ -1406,33 +1439,33 @@ pci_port(CFTypeRef slot_name, int ift, CFStringRef bsdName)
 
                while ((child = IOIteratorNext(child_iterator)) != MACH_PORT_NULL) {
                        if (IOObjectConformsTo(child, kIONetworkInterfaceClass)) {
-                               CFNumberRef     child_if_type;
-                               int             child_ift       = ift;
-
-                               child_if_type = IORegistryEntryCreateCFProperty(child,
-                                                                               CFSTR(kIOInterfaceType),
-                                                                               NULL,
-                                                                               0);
-                               if (child_if_type != NULL) {
-                                       if (!isA_CFNumber(child_if_type) ||
-                                           !CFNumberGetValue(child_if_type, kCFNumberIntType, &child_ift)) {
-                                               // assume that it's a match
-                                               child_ift = ift;
+                               CFMutableDictionaryRef  interface_dict  = NULL;
+
+                               (void) IORegistryEntryCreateCFProperties(child, &interface_dict, NULL, kNilOptions);
+                               if (interface_dict != NULL) {
+                                       CFNumberRef     child_if_type;
+                                       int             child_ift       = ift;
+
+                                       child_if_type = CFDictionaryGetValue(interface_dict, CFSTR(kIOInterfaceType));
+                                       if (child_if_type != NULL) {
+                                               if (!isA_CFNumber(child_if_type) ||
+                                                   !CFNumberGetValue(child_if_type, kCFNumberIntType, &child_ift)) {
+                                                       // assume that it's a match
+                                                       child_ift = ift;
+                                               }
                                        }
-                                       CFRelease(child_if_type);
-                               }
 
-                               if (ift == child_ift) {
-                                       CFStringRef     if_bsdName;
+                                       if (ift == child_ift) {
+                                               CFStringRef     if_bsdName;
 
-                                       if_bsdName = IORegistryEntryCreateCFProperty(child,
-                                                                                    CFSTR(kIOBSDNameKey),
-                                                                                    NULL,
-                                                                                    0);
-                                       if (if_bsdName != NULL) {
-                                               CFArrayAppendValue(port_names, if_bsdName);
-                                               CFRelease(if_bsdName);
+                                               if_bsdName = IODictionaryCopyBSDName(interface_dict);
+                                               if (if_bsdName != NULL) {
+                                                       CFArrayAppendValue(port_names, if_bsdName);
+                                                       CFRelease(if_bsdName);
+                                               }
                                        }
+
+                                       CFRelease(interface_dict);
                                }
                        }
                        IOObjectRelease(child);
@@ -1447,7 +1480,7 @@ pci_port(CFTypeRef slot_name, int ift, CFStringRef bsdName)
                CFArraySortValues(port_names, CFRangeMake(0, n), compare_bsdNames, NULL);
                n = CFArrayGetFirstIndexOfValue(port_names, CFRangeMake(0, n), bsdName);
                if (n != kCFNotFound) {
-                       port_name = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), n + 1);
+                       port_name = CFStringCreateWithFormat(NULL, NULL, CFSTR("%ld"), n + 1);
                }
        }
 
@@ -1459,14 +1492,20 @@ pci_port(CFTypeRef slot_name, int ift, CFStringRef bsdName)
 static Boolean
 pci_slot_info(io_registry_entry_t interface, int ift, CFStringRef *slot_name, CFStringRef *port_name)
 {
-       CFStringRef     bsd_name;
-       Boolean         ok              = FALSE;
-       CFTypeRef       pci_slot_name;
+       CFStringRef             bsd_name        = NULL;
+       CFMutableDictionaryRef  interface_dict  = NULL;
+       Boolean                 ok              = FALSE;
+       CFTypeRef               pci_slot_name;
 
        *slot_name = NULL;
        *port_name = NULL;
 
-       bsd_name = IORegistryEntryCreateCFProperty(interface, CFSTR(kIOBSDNameKey), NULL, 0);
+       (void) IORegistryEntryCreateCFProperties(interface, &interface_dict, NULL, kNilOptions);
+       if (interface_dict != NULL) {
+               bsd_name = IODictionaryCopyBSDName(interface_dict);
+               CFRelease(interface_dict);
+       }
+
        if (bsd_name == NULL) {
                return FALSE;
        }
@@ -1524,6 +1563,7 @@ isBluetoothBuiltin(Boolean *haveController)
        hciController = IOIteratorNext(iter);
        IOObjectRelease(iter);
        if(hciController != MACH_PORT_NULL) {
+#if    !TARGET_IPHONE_SIMULATOR
                CFNumberRef     idVendor;
 
                idVendor = IORegistryEntryCreateCFProperty(hciController, CFSTR(kUSBVendorID), NULL, 0);
@@ -1538,6 +1578,7 @@ isBluetoothBuiltin(Boolean *haveController)
 
                        CFRelease(idVendor);
                }
+#endif // !TARGET_IPHONE_SIMULATOR
 
                IOObjectRelease(hciController);
        }
@@ -1574,6 +1615,7 @@ processUSBInterface(SCNetworkInterfacePrivateRef  interfacePrivate,
                    io_registry_entry_t                 bus,
                    CFDictionaryRef                     bus_dict)
 {
+#if    !TARGET_IPHONE_SIMULATOR
        // capture USB info
        interfacePrivate->usb.name = IORegistryEntrySearchCFProperty(interface,
                                                                     kIOServicePlane,
@@ -1590,6 +1632,7 @@ processUSBInterface(SCNetworkInterfacePrivateRef  interfacePrivate,
                                                                     CFSTR(kUSBProductID),
                                                                     NULL,
                                                                     kIORegistryIterateRecursively | kIORegistryIterateParents);
+#endif // !TARGET_IPHONE_SIMULATOR
 
        return;
 }
@@ -1687,6 +1730,8 @@ merge_override(SCNetworkInterfacePrivateRef       interfacePrivate,
 }
 
 
+#define        BT_PAN_NAME     "Bluetooth PAN"
+
 static Boolean
 processNetworkInterface(SCNetworkInterfacePrivateRef   interfacePrivate,
                        io_registry_entry_t             interface,
@@ -1717,12 +1762,16 @@ processNetworkInterface(SCNetworkInterfacePrivateRef    interfacePrivate,
                case IFT_ETHER :
                        // Type, Hardware
 
-                       if ((IOObjectConformsTo(controller, "IO80211Controller")) ||
-                           (IOObjectConformsTo(controller, "AirPortPCI"       )) ||
-                           (IOObjectConformsTo(controller, "AirPortDriver"    ))) {
+                       if (IOObjectConformsTo(controller, "IO80211Controller") ||
+                           IOObjectConformsTo(controller, "AirPortPCI"       ) ||
+                           IOObjectConformsTo(controller, "AirPortDriver"    )) {
                                interfacePrivate->interface_type        = kSCNetworkInterfaceTypeIEEE80211;
                                interfacePrivate->entity_type           = kSCValNetInterfaceTypeEthernet;
                                interfacePrivate->sort_order            = kSortAirPort;
+                       } else if (IOObjectConformsTo(controller, "AppleThunderboltIPPort")) {
+                               interfacePrivate->interface_type        = kSCNetworkInterfaceTypeEthernet;
+                               interfacePrivate->entity_type           = kSCValNetInterfaceTypeEthernet;
+                               interfacePrivate->sort_order            = kSortThunderbolt;
                        } else if (IOObjectConformsTo(controller, "IOBluetoothBNEPDriver")) {
                                interfacePrivate->interface_type        = kSCNetworkInterfaceTypeEthernet;
                                interfacePrivate->entity_type           = kSCValNetInterfaceTypeEthernet;
@@ -1745,7 +1794,7 @@ processNetworkInterface(SCNetworkInterfacePrivateRef      interfacePrivate,
                                                                      kIORegistryIterateRecursively | kIORegistryIterateParents);
                                if (val != NULL) {
                                        if (isA_CFString(val)) {
-                                               if (CFEqual(val, CFSTR("Bluetooth PAN"))) {
+                                               if (CFEqual(val, CFSTR(BT_PAN_NAME))) {
                                                        interfacePrivate->interface_type        = kSCNetworkInterfaceTypeEthernet;
                                                        interfacePrivate->entity_type           = kSCValNetInterfaceTypeEthernet;
                                                        interfacePrivate->sort_order            = kSortBluetoothPAN_GN;
@@ -1808,6 +1857,11 @@ processNetworkInterface(SCNetworkInterfacePrivateRef     interfacePrivate,
 
                        // location
                        interfacePrivate->location = IODictionaryCopyCFStringValue(interface_dict, CFSTR(kIOLocation));
+                       if ((interfacePrivate->location != NULL) &&
+                           (CFStringGetLength(interfacePrivate->location) == 0)) {
+                               CFRelease(interfacePrivate->location);
+                               interfacePrivate->location = NULL;
+                       }
 
                        // VLAN support
                        num = CFDictionaryGetValue(controller_dict, CFSTR(kIOFeatures));
@@ -1821,6 +1875,14 @@ processNetworkInterface(SCNetworkInterfacePrivateRef     interfacePrivate,
                        // localized name
                        if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeIEEE80211)) {
                                interfacePrivate->localized_key = CFSTR("airport");
+                       } else if (interfacePrivate->sort_order == kSortThunderbolt) {
+                               if ((interfacePrivate->location == NULL) ||
+                                   (CFStringGetLength(interfacePrivate->location) == 0)) {
+                                       interfacePrivate->localized_key = CFSTR("thunderbolt");
+                               } else {
+                                       interfacePrivate->localized_key  = CFSTR("multithunderbolt");
+                                       interfacePrivate->localized_arg1 = CFRetain(interfacePrivate->location);
+                               }
                        } else if (interfacePrivate->sort_order == kSortBluetoothPAN_GN) {
                                interfacePrivate->localized_key  = CFSTR("bluetooth-pan-gn");
                        } else if (interfacePrivate->sort_order == kSortBluetoothPAN_NAP) {
@@ -1890,7 +1952,7 @@ processNetworkInterface(SCNetworkInterfacePrivateRef      interfacePrivate,
                                                // set interface "name"
                                                if (!update_interface_name(interfacePrivate, interface, TRUE)) {
                                                        interfacePrivate->localized_key  = CFSTR("usb-ether");
-                                                       interfacePrivate->localized_arg1 = IODictionaryCopyCFStringValue(interface_dict, CFSTR(kIOBSDNameKey));
+                                                       interfacePrivate->localized_arg1 = IODictionaryCopyBSDName(interface_dict);
                                                }
                                        }
                                        CFRelease(provider);
@@ -1899,7 +1961,7 @@ processNetworkInterface(SCNetworkInterfacePrivateRef      interfacePrivate,
                                if (interfacePrivate->localized_key == NULL) {
                                        // if no provider, not a PCI device, or no slot information
                                        interfacePrivate->localized_key  = CFSTR("generic-ether");
-                                       interfacePrivate->localized_arg1 = IODictionaryCopyCFStringValue(interface_dict, CFSTR(kIOBSDNameKey));
+                                       interfacePrivate->localized_arg1 = IODictionaryCopyBSDName(interface_dict);
                                }
                        }
 
@@ -1956,7 +2018,7 @@ processNetworkInterface(SCNetworkInterfacePrivateRef      interfacePrivate,
        }
 
        // Device
-       interfacePrivate->entity_device = IODictionaryCopyCFStringValue(interface_dict, CFSTR(kIOBSDNameKey));
+       interfacePrivate->entity_device = IODictionaryCopyBSDName(interface_dict);
 
        // Hardware (MAC) address
        data = CFDictionaryGetValue(controller_dict, CFSTR(kIOMACAddress));
@@ -1964,6 +2026,12 @@ processNetworkInterface(SCNetworkInterfacePrivateRef     interfacePrivate,
                interfacePrivate->address = CFRetain(data);
        }
 
+       // interface prefix
+       str = CFDictionaryGetValue(interface_dict, CFSTR(kIOInterfaceNamePrefix));
+       if (isA_CFString(str)) {
+               interfacePrivate->prefix = CFRetain(str);
+       }
+
        // interface unit
        num = CFDictionaryGetValue(interface_dict, CFSTR(kIOInterfaceUnit));
        if (isA_CFNumber(num) &&
@@ -2448,40 +2516,41 @@ createInterface(io_registry_entry_t interface, processInterface func)
 
        /* get the controller node */
        kr = IORegistryEntryGetParentEntry(interface, kIOServicePlane, &controller);
-       if (kr != KERN_SUCCESS) {
+       if (kr != kIOReturnSuccess) {
                SCLog(TRUE, LOG_DEBUG, CFSTR("createInterface IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr);
                goto done;
        }
 
        /* get the dictionary associated with the node */
        kr = IORegistryEntryCreateCFProperties(controller, &controller_dict, NULL, kNilOptions);
-       if (kr != KERN_SUCCESS) {
+       if (kr != kIOReturnSuccess) {
                SCLog(TRUE, LOG_DEBUG, CFSTR("createInterface IORegistryEntryCreateCFProperties() failed, kr = 0x%x"), kr);
                goto done;
        }
 
        /* get the bus node */
        kr = IORegistryEntryGetParentEntry(controller, kIOServicePlane, &bus);
-       if (kr != KERN_SUCCESS) {
+       if (kr != kIOReturnSuccess) {
                SCLog(TRUE, LOG_DEBUG, CFSTR("createInterface IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr);
                goto done;
        }
 
        /* get the dictionary associated with the node */
        kr = IORegistryEntryCreateCFProperties(bus, &bus_dict, NULL, kNilOptions);
-       if (kr != KERN_SUCCESS) {
+       if (kr != kIOReturnSuccess) {
                SCLog(TRUE, LOG_DEBUG, CFSTR("createInterface IORegistryEntryCreateCFProperties() failed, kr = 0x%x"), kr);
                goto done;
        }
 
        /* get the registry entry ID */
        kr = IORegistryEntryGetRegistryEntryID(interface, &entryID);
-       if (kr != KERN_SUCCESS) {
+       if (kr != kIOReturnSuccess) {
                SCLog(TRUE, LOG_DEBUG, CFSTR("createInterface IORegistryEntryGetRegistryEntryID() failed, kr = 0x%x"), kr);
                goto done;
        }
 
        interfacePrivate = __SCNetworkInterfaceCreatePrivate(NULL, NULL, NULL, NULL);
+       assert(interfacePrivate != NULL);
        interfacePrivate->path = __SC_IORegistryEntryCopyPath(interface, kIOServicePlane);
        interfacePrivate->entryID = entryID;
 
@@ -3360,6 +3429,7 @@ _SCNetworkInterfaceCreateWithEntity(CFAllocatorRef                allocator,
        if (matching_interfaces != NULL) {
                CFIndex                 n;
                SCPreferencesRef        prefs;
+               Boolean                 temp_preferences        = FALSE;
 
                n = CFArrayGetCount(matching_interfaces);
                switch (n) {
@@ -3377,7 +3447,21 @@ _SCNetworkInterfaceCreateWithEntity(CFAllocatorRef               allocator,
                                if (!CFEqual(ifType, kSCValNetInterfaceTypeEthernet)) {
                                        break;
                                }
-                               prefs = SCPreferencesCreate(NULL, CFSTR("SCNetworkInterface"), NULL);
+
+                               if (CFDictionaryGetValueIfPresent(interface_entity,
+                                                                 kSCPropUserDefinedName,
+                                                                 (const void **)&ifName) &&
+                                   CFEqual(ifName, CFSTR(BT_PAN_NAME))) {
+                                       break;
+                               }
+
+                               prefs = (service != NULL) ? ((SCNetworkServicePrivateRef)service)->prefs : NULL;
+                               if (prefs == NULL) {
+                                       prefs = SCPreferencesCreate(NULL, CFSTR("SCNetworkInterface"), NULL);
+                                       if (prefs != NULL) {
+                                               temp_preferences = TRUE;
+                                       }
+                               }
                                if (prefs == NULL) {
                                        break;
                                }
@@ -3395,7 +3479,7 @@ _SCNetworkInterfaceCreateWithEntity(CFAllocatorRef                allocator,
                                    && !CFDictionaryContainsKey(interface_entity, CFSTR("_NO_VLAN_INTERFACES_"))) {
                                        interfacePrivate = (SCNetworkInterfacePrivateRef)findVLANInterface(prefs, ifDevice);
                                }
-                               CFRelease(prefs);
+                               if (temp_preferences) CFRelease(prefs);
                                break;
                        default :
                                if (ifUnique != NULL) {
@@ -3486,6 +3570,12 @@ _SCNetworkInterfaceCreateWithEntity(CFAllocatorRef               allocator,
                                if (_SCNetworkInterfaceMatchesName(name, CFSTR("iPhone"))) {
                                        interfacePrivate->localized_key = CFSTR("iPhone");
                                        interfacePrivate->sort_order    = kSortTethered;
+                               } else if (_SCNetworkInterfaceMatchesName(name, CFSTR("iPad"))) {
+                                       interfacePrivate->localized_key = CFSTR("iPad");
+                                       interfacePrivate->sort_order    = kSortTethered;
+                               } else if (_SCNetworkInterfaceMatchesName(name, CFSTR("thunderbolt"))) {
+                                       interfacePrivate->localized_key = CFSTR("thunderbolt");
+                                       interfacePrivate->sort_order    = kSortThunderbolt;
                                } else if (_SCNetworkInterfaceMatchesName(name, CFSTR("bluetooth-pan-gn"))) {
                                        interfacePrivate->localized_key = CFSTR("bluetooth-pan-gn");
                                        interfacePrivate->sort_order    = kSortBluetoothPAN_GN;
@@ -3651,7 +3741,7 @@ __SCNetworkInterfaceCopyAll_IONetworkInterface(void)
        CFDictionaryRef         matching;
        CFArrayRef              new_interfaces;
 
-       // get Ethernet, Firewire, and AirPort interfaces
+       // get Ethernet, Firewire, Thunderbolt, and AirPort interfaces
 
        matching = IOServiceMatching(kIONetworkInterfaceClass);
        new_interfaces = findMatchingInterfaces(matching, processNetworkInterface);
@@ -3721,9 +3811,9 @@ __SCNetworkInterfaceCopyAll_RS232()
 static void
 addBTPANInterface(SCPreferencesRef prefs, CFMutableArrayRef all_interfaces)
 {
-       CFIndex         i;
-       CFIndex         n;
-       CFArrayRef      services;
+       CFIndex                 i;
+       SCNetworkInterfaceRef   interface;
+       CFIndex                 n;
 
        n = CFArrayGetCount(all_interfaces);
        for (i = 0; i < n; i++) {
@@ -3736,24 +3826,11 @@ addBTPANInterface(SCPreferencesRef prefs, CFMutableArrayRef all_interfaces)
                }
        }
 
-       services = SCNetworkServiceCopyAll(prefs);
-       if (services != NULL) {
-               n = CFArrayGetCount(services);
-               for (i = 0; i < n; i++) {
-                       SCNetworkInterfaceRef   interface;
-                       SCNetworkServiceRef     service;
-
-                       service = CFArrayGetValueAtIndex(services, i);
-                       interface = SCNetworkServiceGetInterface(service);
-                       if ((interface != NULL) &&
-                           _SCNetworkInterfaceIsBluetoothPAN(interface)) {
-                               // include BT-PAN interface
-                               CFArrayAppendValue(all_interfaces, interface);
-                               break;
-                       }
-               }
-
-               CFRelease(services);
+       interface = _SCNetworkInterfaceCopyBTPANInterface();
+       if (interface != NULL) {
+               // include BT-PAN interface
+               CFArrayAppendValue(all_interfaces, interface);
+               CFRelease(interface);
        }
 
        return;
@@ -3861,7 +3938,7 @@ _SCNetworkInterfaceCopyAllWithPreferences(SCPreferencesRef prefs)
 
        all_interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
 
-       // get Ethernet, Firewire, and AirPort interfaces
+       // get Ethernet, Firewire, Thunderbolt, and AirPort interfaces
        new_interfaces = __SCNetworkInterfaceCopyAll_IONetworkInterface();
        if (new_interfaces != NULL) {
                add_interfaces(all_interfaces, new_interfaces);
@@ -4563,7 +4640,7 @@ copy_display_name(SCNetworkInterfaceRef interface, Boolean localized, Boolean ol
 }
 
 
-#if    !TARGET_OS_EMBEDDED && !TARGET_IPHONE_SIMULATOR
+#if    !TARGET_OS_IPHONE
 __private_extern__
 CFStringRef
 __SCNetworkInterfaceCopyXLocalizedDisplayName(SCNetworkInterfaceRef interface)
@@ -4594,7 +4671,7 @@ __SCNetworkInterfaceCopyXNonLocalizedDisplayName(SCNetworkInterfaceRef interface
        localized_name = copy_display_name(interface, FALSE, TRUE);
        return localized_name;
 }
-#endif // !TARGET_OS_EMBEDDED && !TARGET_IPHONE_SIMULATOR
+#endif // !TARGET_OS_IPHONE
 
 
 __private_extern__
@@ -6045,6 +6122,10 @@ _SCNetworkInterfaceCopyInterfaceInfo(SCNetworkInterfaceRef interface)
        SCNetworkInterfacePrivateRef    interfacePrivate        = (SCNetworkInterfacePrivateRef)interface;
        CFStringRef                     name;
 
+       if (interface == NULL) {
+               return NULL;
+       }
+
        info = CFDictionaryCreateMutable(NULL,
                                         0,
                                         &kCFTypeDictionaryKeyCallBacks,
@@ -6058,6 +6139,7 @@ _SCNetworkInterfaceCopyInterfaceInfo(SCNetworkInterfaceRef interface)
 
        // add USB info
        if ((interfacePrivate->usb.vid != NULL) || (interfacePrivate->usb.pid != NULL)) {
+#if    !TARGET_IPHONE_SIMULATOR
                if (interfacePrivate->usb.name != NULL) {
                        CFDictionaryAddValue(info, CFSTR(kUSBProductString), interfacePrivate->usb.name);
                }
@@ -6067,6 +6149,7 @@ _SCNetworkInterfaceCopyInterfaceInfo(SCNetworkInterfaceRef interface)
                if (interfacePrivate->usb.pid != NULL) {
                        CFDictionaryAddValue(info, CFSTR(kUSBProductID), interfacePrivate->usb.pid);
                }
+#endif // !TARGET_IPHONE_SIMULATOR
        }
 
        if (CFDictionaryGetCount(info) == 0) {
@@ -6115,6 +6198,15 @@ _SCNetworkInterfaceGetHardwareAddress(SCNetworkInterfaceRef interface)
 }
 
 
+CFStringRef
+_SCNetworkInterfaceGetIOInterfaceNamePrefix(SCNetworkInterfaceRef interface)
+{
+       SCNetworkInterfacePrivateRef    interfacePrivate        = (SCNetworkInterfacePrivateRef)interface;
+
+       return interfacePrivate->prefix;
+}
+
+
 CFNumberRef
 _SCNetworkInterfaceGetIOInterfaceType(SCNetworkInterfaceRef interface)
 {
@@ -6164,6 +6256,53 @@ _SCNetworkInterfaceIsBuiltin(SCNetworkInterfaceRef interface)
 #pragma mark SCNetworkInterface SPIs
 
 
+#if    !TARGET_OS_EMBEDDED
+
+SCNetworkInterfaceRef
+_SCNetworkInterfaceCopyBTPANInterface(void)
+{
+       CFDictionaryRef         dict;
+       SCNetworkInterfaceRef   interface       = NULL;
+       CFStringRef             key;
+
+       key = SCDynamicStoreKeyCreate(NULL, CFSTR("%@" "InterfaceNamer"), kSCDynamicStoreDomainPlugin);
+       dict = SCDynamicStoreCopyValue(NULL, key);
+       CFRelease(key);
+       if (dict != NULL) {
+               CFStringRef     if_name;
+
+               if (isA_CFDictionary(dict) &&
+                   CFDictionaryGetValueIfPresent(dict,
+                                                 CFSTR("_" BT_PAN_NAME "_"),
+                                                 (const void **)&if_name) &&
+                   isA_CFString(if_name)) {
+                       CFMutableDictionaryRef  entity;
+
+                       entity = CFDictionaryCreateMutable(NULL,
+                                                          0,
+                                                          &kCFTypeDictionaryKeyCallBacks,
+                                                          &kCFTypeDictionaryValueCallBacks);
+                       CFDictionarySetValue(entity,
+                                            kSCPropNetInterfaceType,
+                                            kSCValNetInterfaceTypeEthernet);
+                       CFDictionarySetValue(entity,
+                                            kSCPropNetInterfaceDeviceName,
+                                            if_name);
+                       CFDictionarySetValue(entity,
+                                            kSCPropUserDefinedName,
+                                            CFSTR(BT_PAN_NAME));
+                       interface = _SCNetworkInterfaceCreateWithEntity(NULL, entity, NULL);
+                       CFRelease(entity);
+               }
+
+               CFRelease(dict);
+       }
+
+       return interface;
+}
+#endif // !TARGET_OS_EMBEDDED
+
+
 CFStringRef
 _SCNetworkInterfaceCopySlashDevPath(SCNetworkInterfaceRef interface)
 {
@@ -6328,6 +6467,48 @@ _SCNetworkInterfaceIsTethered(SCNetworkInterfaceRef interface)
 }
 
 
+Boolean
+_SCNetworkInterfaceIsThunderbolt(SCNetworkInterfaceRef interface)
+{
+       SCNetworkInterfacePrivateRef    interfacePrivate        = (SCNetworkInterfacePrivateRef)interface;
+       CFStringRef                     interfaceType;
+
+       if (!isA_SCNetworkInterface(interface)) {
+               return FALSE;
+       }
+
+       interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
+       if (CFEqual(interfaceType, kSCNetworkInterfaceTypeBridge)) {
+               CFIndex         i;
+               CFArrayRef      members;
+               CFIndex         n;
+
+               members = SCBridgeInterfaceGetMemberInterfaces(interface);
+               n = (members != NULL) ? CFArrayGetCount(members) : 0;
+               if (n == 0) {
+                       // if an empty bridge
+                       return FALSE;
+               }
+
+               for (i = 0; i < n; i++) {
+                       SCNetworkInterfaceRef           member;
+                       SCNetworkInterfacePrivateRef    memberPrivate;
+
+                       member = CFArrayGetValueAtIndex(members, i);
+                       memberPrivate = (SCNetworkInterfacePrivateRef)member;
+                       if (memberPrivate->sort_order != kSortThunderbolt) {
+                               return FALSE;
+                       }
+               }
+
+               // if Ethernet Bridge interface with only Thunderbolt [IP] members
+               return TRUE;
+       }
+
+       return (interfacePrivate->sort_order == kSortThunderbolt);
+}
+
+
 #pragma mark -
 #pragma mark SCNetworkInterface [internal] SPIs
 
index 73e8ff8a4968be6d989778590ed4079c1002d6ca..efdae042d5d5a2046e0df9a1b892364bdcc9c36a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003-2012 Apple Inc. All rights reserved.
+ * Copyright (c) 2003-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -44,6 +44,7 @@
 #include <SystemConfiguration/SystemConfiguration.h>
 #include <SystemConfiguration/SCValidation.h>
 #include <SystemConfiguration/SCPrivate.h>
+#include <SystemConfiguration/VPNAppLayerPrivate.h>
 #include <pthread.h>
 #include <libkern/OSAtomic.h>
 
 #define s6_addr16 __u6_addr.__u6_addr16
 #endif
 
+#include "SCNetworkConnectionInternal.h"
+
 #include "SCNetworkReachabilityInternal.h"
 
 #include <ppp/ppp_msg.h>
+#include <network_information.h>
 
-#if    !TARGET_IPHONE_SIMULATOR
+#if    defined(HAVE_IPSEC_STATUS) || defined(HAVE_VPN_STATUS)
 #include <ppp/PPPControllerPriv.h>
-#endif // !TARGET_IPHONE_SIMULATOR
-
+#endif // !defined(HAVE_IPSEC_STATUS) || defined(HAVE_VPN_STATUS)
 
 
-#if    ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 40000)) && !TARGET_IPHONE_SIMULATOR
-#define        HAVE_GETADDRINFO_INTERFACE_ASYNC_CALL
-#endif // ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 40000)) && !TARGET_IPHONE_SIMULATOR
-
-#if    ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 40000)) && !TARGET_IPHONE_SIMULATOR && !TARGET_OS_EMBEDDED_OTHER
-#define        HAVE_IPSEC_STATUS
-#define        HAVE_VPN_STATUS
-#endif // ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 40000)) && !TARGET_IPHONE_SIMULATOR && !TARGET_OS_EMBEDDED_OTHER
 
 
 
 #define        DEBUG_REACHABILITY_TYPE_ADDRESSPAIR             "create w/address pair"
 #define        DEBUG_REACHABILITY_TYPE_ADDRESSPAIR_OPTIONS     "            + options"
 
+#define        DNS_FLAGS_FORMAT        "[%s%s%s%s]"
+#define        DNS_FLAGS_VALUES(t)     t->dnsHaveV4      ? "4" : "",   \
+                               t->dnsHaveV6      ? "6" : "",   \
+                               t->dnsHaveTimeout ? "T" : "",   \
+                               t->dnsHaveError   ? "E" : ""
+
 
 static pthread_mutexattr_t     lock_attr;
 
@@ -136,25 +137,12 @@ _getaddrinfo_interface_async_call(const char                      *nodename,
                                  const char                    *interface,
                                  getaddrinfo_async_callback    callback,
                                  void                          *context);
-#endif /* HAVE_GETADDRINFO_INTERFACE_ASYNC_CALL */
+#endif // HAVE_GETADDRINFO_INTERFACE_ASYNC_CALL
 
 
 #define SCNETWORKREACHABILITY_TRIGGER_KEY      CFSTR("com.apple.SCNetworkReachability:FORCE-CHANGE")
 
 
-// how long (minimum time, us) to wait before retrying DNS query after EAI_NONAME
-#define EAI_NONAME_RETRY_DELAY_USEC    250000                  // 250ms
-
-// how long (maximum time, us) after DNS configuration change we accept EAI_NONAME
-// without question.
-#define EAI_NONAME_RETRY_LIMIT_USEC    2500000                 // 2.5s
-
-
-// how long (maximum time, ns) to wait for a long-lived-query callback before
-// we assume EAI_NONAME.
-#define LLQ_TIMEOUT_NSEC               30 * NSEC_PER_SEC       // 30s
-
-
 #define        N_QUICK 64
 
 
@@ -211,16 +199,20 @@ static const struct addrinfo      HINTS_DEFAULT   = {
 static const struct timeval    TIME_ZERO       = { 0, 0 };
 
 
-static Boolean                 D_llqBypass     = FALSE;
-static int                     llqCount        = 0;
-static DNSServiceRef           llqMain         = NULL;
-static CFMutableSetRef         llqUpdated      = NULL;
+static int                     dnsCount        = 0;
+static DNSServiceRef           dnsMain         = NULL;
+#ifdef USE_DNSSERVICEGETADDRINFO
+static CFMutableSetRef         dnsUpdated      = NULL;
+#endif // USE_DNSSERVICEGETADDRINFO
 
 
 #ifdef HAVE_REACHABILITY_SERVER
 static Boolean                 D_serverBypass  = FALSE;
 #endif // HAVE_REACHABILITY_SERVER
 
+static Boolean                 D_nwiBypass     = FALSE;
+
+
 
 #if    !TARGET_OS_IPHONE
 /*
@@ -234,11 +226,39 @@ static IOPMSystemPowerStateCapabilities   power_capabilities      = kIOPMSytemPowerStat
  * host "something has changed" notifications
  */
 
+// Note: protected by _hn_target_queue()
 static SCDynamicStoreRef       hn_store        = NULL;
-static dispatch_queue_t                hn_dispatchQueue = NULL;
 static CFMutableSetRef         hn_targets      = NULL;
 
 
+static dispatch_queue_t
+_hn_changes_queue()
+{
+       static dispatch_once_t  once;
+       static dispatch_queue_t q = NULL;
+
+       dispatch_once(&once, ^{
+               q = dispatch_queue_create("SCNetworkReachabilty.handleChanges", NULL);
+       });
+
+       return q;
+}
+
+
+static dispatch_queue_t
+_hn_target_queue()
+{
+       static dispatch_once_t  once;
+       static dispatch_queue_t q;
+
+       dispatch_once(&once, ^{
+               q = dispatch_queue_create("SCNetworkReachabilty.targetManagement", NULL);
+       });
+
+       return q;
+}
+
+
 /*
  * DNS configuration
  */
@@ -249,60 +269,56 @@ typedef struct {
 } dns_configuration_t;
 
 
+// Note: protected by "dns_lock"
 static pthread_mutex_t         dns_lock                = PTHREAD_MUTEX_INITIALIZER;
 static dns_configuration_t     *dns_configuration      = NULL;
 static int                     dns_token;
 static Boolean                 dns_token_valid         = FALSE;
 
 
+
+
 typedef enum {
        dns_query_sync,
        dns_query_async,
-       dns_query_llq
-} dns_query_type;
+       dns_query_mdns,
+} query_type;
 
 
 static void
-__dns_query_start(struct timeval       *dnsQueryStart,
-                 struct timeval        *dnsQueryEnd)
+__mark_operation_start(struct timeval  *queryStart,
+                      struct timeval   *queryEnd)
 {
-       (void) gettimeofday(dnsQueryStart, NULL);
-       *dnsQueryEnd = TIME_ZERO;
+       (void) gettimeofday(queryStart, NULL);
+       *queryEnd = TIME_ZERO;
 
        return;
 }
 
 
 static void
-__dns_query_end(SCNetworkReachabilityRef       target,
-               Boolean                         found,
-               dns_query_type                  query_type,
-               struct timeval                  *dnsQueryStart,
-               struct timeval                  *dnsQueryEnd)
+__mark_operation_end(SCNetworkReachabilityRef  target,
+                    Boolean                    found,
+                    query_type                 query_type,
+                    struct timeval             *queryStart,
+                    struct timeval             *queryEnd)
 {
-       struct timeval                  dnsQueryElapsed;
-       Boolean                         firstQuery;
+       struct timeval                  queryElapsed;
        SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
 
-       // report initial or updated query time
-       firstQuery = !timerisset(dnsQueryEnd);
-
-       (void) gettimeofday(dnsQueryEnd, NULL);
+       (void) gettimeofday(queryEnd, NULL);
 
        if (!_sc_debug) {
                return;
        }
 
-       if (!timerisset(dnsQueryStart)) {
+       if (!timerisset(queryStart)) {
                return;
        }
 
-       timersub(dnsQueryEnd, dnsQueryStart, &dnsQueryElapsed);
+       timersub(queryEnd, queryStart, &queryElapsed);
        switch (query_type) {
 
-//             #define QUERY_TIME__FMT "%d.%3.3d"
-//             #define QUERY_TIME__DIV 1000
-
                #define QUERY_TIME__FMT "%d.%6.6d"
                #define QUERY_TIME__DIV 1
 
@@ -311,25 +327,25 @@ __dns_query_end(SCNetworkReachabilityRef  target,
                              CFSTR("%ssync DNS complete%s (query time = " QUERY_TIME__FMT ")"),
                              targetPrivate->log_prefix,
                              found ? "" : ", host not found",
-                             dnsQueryElapsed.tv_sec,
-                             dnsQueryElapsed.tv_usec / QUERY_TIME__DIV);
+                             queryElapsed.tv_sec,
+                             queryElapsed.tv_usec / QUERY_TIME__DIV);
                        break;
                case dns_query_async :
                        SCLog(TRUE, LOG_INFO,
                              CFSTR("%sasync DNS complete%s (query time = " QUERY_TIME__FMT ")"),
                              targetPrivate->log_prefix,
                              found ? "" : ", host not found",
-                             dnsQueryElapsed.tv_sec,
-                             dnsQueryElapsed.tv_usec / QUERY_TIME__DIV);
+                             queryElapsed.tv_sec,
+                             queryElapsed.tv_usec / QUERY_TIME__DIV);
                        break;
-               case dns_query_llq :
+               case dns_query_mdns :
                        SCLog(TRUE, LOG_INFO,
-                             CFSTR("%sDNS updated%s (%s = " QUERY_TIME__FMT ")"),
+                             CFSTR("%s[m]DNS query complete%s (query time = " QUERY_TIME__FMT "), " DNS_FLAGS_FORMAT),
                              targetPrivate->log_prefix,
                              found ? "" : ", host not found",
-                             firstQuery ? "query time" : "updated after",
-                             dnsQueryElapsed.tv_sec,
-                             dnsQueryElapsed.tv_usec / QUERY_TIME__DIV);
+                             queryElapsed.tv_sec,
+                             queryElapsed.tv_usec / QUERY_TIME__DIV,
+                             DNS_FLAGS_VALUES(targetPrivate));
                        break;
        }
 
@@ -361,11 +377,27 @@ __reach_changed(ReachabilityInfo *r1, ReachabilityInfo *r2)
 
 
 static __inline__ void
-_reach_set(ReachabilityInfo *dst, const ReachabilityInfo *src, uint64_t cycle)
+_reach_set(ReachabilityInfo            *dst,
+          const ReachabilityInfo       *src,
+          uint64_t                     cycle,
+          unsigned int                 requested_if_index,
+          const char                   *requested_if_name)
 {
        memcpy(dst, src, sizeof(ReachabilityInfo));
        dst->cycle = cycle;
 
+       if (!(dst->flags & kSCNetworkReachabilityFlagsReachable) ||
+               (dst->flags & kSCNetworkReachabilityFlagsConnectionRequired)) {
+               // if not reachable or connection required, return the
+               // requested if_index and if_name.
+               dst->if_index = requested_if_index;
+               if (requested_if_name != NULL) {
+                       strlcpy(dst->if_name, requested_if_name, sizeof(dst->if_name));
+               } else {
+                       dst->if_name[0] = '\0';
+               }
+       }
+
        return;
 }
 
@@ -510,12 +542,20 @@ ReachabilityStoreInfo_save(ReachabilityStoreInfoRef store_info)
 static Boolean
 ReachabilityStoreInfo_fill(ReachabilityStoreInfoRef store_info)
 {
+       CFStringRef             key;
+       CFMutableArrayRef       keys;
        CFStringRef             pattern;
        CFMutableArrayRef       patterns;
 
+       keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
        patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
 
        // get info for IPv4 services
+       key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+                                                        kSCDynamicStoreDomainState,
+                                                        kSCEntNetIPv4);
+       CFArrayAppendValue(keys, key);
+       CFRelease(key);
        pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
                                                              kSCDynamicStoreDomainSetup,
                                                              kSCCompAnyRegex,
@@ -530,6 +570,11 @@ ReachabilityStoreInfo_fill(ReachabilityStoreInfoRef store_info)
        CFRelease(pattern);
 
        // get info for IPv6 services
+       key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+                                                        kSCDynamicStoreDomainState,
+                                                        kSCEntNetIPv6);
+       CFArrayAppendValue(keys, key);
+       CFRelease(key);
        pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
                                                              kSCDynamicStoreDomainSetup,
                                                              kSCCompAnyRegex,
@@ -557,7 +602,6 @@ ReachabilityStoreInfo_fill(ReachabilityStoreInfoRef store_info)
        CFArrayAppendValue(patterns, pattern);
        CFRelease(pattern);
 
-#if    !TARGET_IPHONE_SIMULATOR
        // get info for VPN services
        pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
                                                              kSCDynamicStoreDomainSetup,
@@ -571,7 +615,6 @@ ReachabilityStoreInfo_fill(ReachabilityStoreInfoRef store_info)
                                                              kSCEntNetVPN);
        CFArrayAppendValue(patterns, pattern);
        CFRelease(pattern);
-#endif // !TARGET_IPHONE_SIMULATOR
 
        // get info for IPSec services
 //     pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
@@ -597,7 +640,8 @@ ReachabilityStoreInfo_fill(ReachabilityStoreInfoRef store_info)
 
 
        // get the SCDynamicStore info
-       store_info->dict = SCDynamicStoreCopyMultiple(store_info->store, NULL, patterns);
+       store_info->dict = SCDynamicStoreCopyMultiple(store_info->store, keys, patterns);
+       CFRelease(keys);
        CFRelease(patterns);
        if (store_info->dict == NULL) {
                return FALSE;
@@ -711,6 +755,12 @@ ReachabilityStoreInfo_update(ReachabilityStoreInfoRef      store_info,
 
 
 #pragma mark -
+#pragma mark Legacy Reachability Functions - to be deprecated.
+
+// Note: these can/should be removed when the iOS simulator will only
+//       be used on a system with the enhanced (with reachability
+//       flags) NWI content.
+
 #pragma mark PPP info
 
 
@@ -983,12 +1033,9 @@ updatePPPAvailable(ReachabilityStoreInfoRef       store_info,
        return sc_status;
 }
 
-
-#pragma mark -
 #pragma mark VPN info
 
 
-#if    !TARGET_IPHONE_SIMULATOR
 static int
 updateVPNStatus(ReachabilityStoreInfoRef       store_info,
                const struct sockaddr           *sa,
@@ -1216,10 +1263,8 @@ updateVPNAvailable(ReachabilityStoreInfoRef      store_info,
 
        return sc_status;
 }
-#endif // !TARGET_IPHONE_SIMULATOR
 
 
-#pragma mark -
 #pragma mark IPSec info
 
 
@@ -1398,7 +1443,7 @@ typedef struct {
 
 /*
  * route_get()
- *     returns zero if route exists an data returned, EHOSTUNREACH
+ *     returns zero if route exists and data returned, EHOSTUNREACH
  *     if no route, or errno for any other error.
  */
 static int
@@ -1572,7 +1617,7 @@ route_get(const struct sockaddr   *address,
                        }
                }
        }
-#endif /* LOG_RTADDRS */
+#endif // LOG_RTADDRS
 
        if ((info->rti_info[RTAX_IFP] == NULL) ||
            (info->rti_info[RTAX_IFP]->sa_family != AF_LINK)) {
@@ -1591,31 +1636,21 @@ route_get(const struct sockaddr *address,
        return 0;
 }
 
-
-static Boolean
-checkAddress(ReachabilityStoreInfoRef  store_info,
-            const struct sockaddr      *address,
-            unsigned int               if_index,
-            ReachabilityInfo           *reach_info,
-            const char                 *log_prefix)
+static int
+checkAddressRoute(const struct sockaddr        *address,
+                 unsigned int          if_index,
+                 char                  *if_name,
+                 struct ifreq          *ifr,
+                 ReachabilityInfo      *reach_info,
+                 route_info            *info,
+                 int                   *sc_status,
+                 const char            *log_prefix)
 {
-       route_info              info;
-       struct ifreq            ifr;
-       char                    if_name[IFNAMSIZ];
        int                     isock           = -1;
-       int                     ret;
-       int                     sc_status       = kSCStatusReachabilityUnknown;
-       CFStringRef             server          = NULL;
+       int                     ret             = 0;
        char                    *statusMessage  = NULL;
        struct sockaddr_in      v4mapped;
 
-       _reach_set(reach_info, &NOT_REACHABLE, reach_info->cycle);
-
-       if (address == NULL) {
-               /* special case: check only for available paths off the system */
-               goto checkAvailable;
-       }
-
        switch (address->sa_family) {
                case AF_INET :
                case AF_INET6 :
@@ -1645,7 +1680,8 @@ checkAddress(ReachabilityStoreInfoRef     store_info,
                        SCLog(TRUE, LOG_INFO,
                              CFSTR("checkAddress(): unexpected address family %d"),
                              address->sa_family);
-                       sc_status = kSCStatusInvalidArgument;
+                       *sc_status = kSCStatusInvalidArgument;
+                       ret = EPERM;
                        goto done;
        }
 
@@ -1663,16 +1699,16 @@ checkAddress(ReachabilityStoreInfoRef   store_info,
                }
        }
 
-       ret = route_get(address, if_index, &info);
+       ret = route_get(address, if_index, info);
        switch (ret) {
                case 0 :
                        break;
                case EHOSTUNREACH :
                        // if no route
-                       goto checkAvailable;
+                       goto done;
                default :
                        // if error
-                       sc_status = ret;
+                       *sc_status = ret;
                        goto done;
        }
 
@@ -1680,45 +1716,48 @@ checkAddress(ReachabilityStoreInfoRef   store_info,
 
        isock = socket(AF_INET, SOCK_DGRAM, 0);
        if (isock == -1) {
+               ret = errno;
                SCLog(TRUE, LOG_ERR, CFSTR("socket() failed: %s"), strerror(errno));
                goto done;
        }
 
-       bzero(&ifr, sizeof(ifr));
-       bcopy(info.sdl->sdl_data, ifr.ifr_name, info.sdl->sdl_nlen);
+       bzero(ifr, sizeof(*ifr));
+       bcopy(info->sdl->sdl_data, ifr->ifr_name, info->sdl->sdl_nlen);
 
-       if (ioctl(isock, SIOCGIFFLAGS, (char *)&ifr) == -1) {
-               SCLog(TRUE, LOG_ERR, CFSTR("ioctl() failed: %s"), strerror(errno));
+       if (ioctl(isock, SIOCGIFFLAGS, (char *)ifr) == -1) {
+               ret = errno;
+               SCLog(TRUE, LOG_ERR, CFSTR("ioctl(SIOCGIFFLAGS) failed: %s"), strerror(errno));
                goto done;
        }
 
-       if (!(ifr.ifr_flags & IFF_UP)) {
-               goto checkAvailable;
+       if (!(ifr->ifr_flags & IFF_UP)) {
+               ret = EHOSTUNREACH;
+               goto done;
        }
 
        statusMessage = "isReachable";
        reach_info->flags |= kSCNetworkReachabilityFlagsReachable;
 
-       if (info.rtm->rtm_flags & RTF_LOCAL) {
+       if (info->rtm->rtm_flags & RTF_LOCAL) {
                statusMessage = "isReachable (is a local address)";
                reach_info->flags |= kSCNetworkReachabilityFlagsIsLocalAddress;
-       } else if (ifr.ifr_flags & IFF_LOOPBACK) {
+       } else if (ifr->ifr_flags & IFF_LOOPBACK) {
                statusMessage = "isReachable (is loopback network)";
                reach_info->flags |= kSCNetworkReachabilityFlagsIsLocalAddress;
-       } else if ((info.rti_info[RTAX_IFA] != NULL) &&
-                  (info.rti_info[RTAX_IFA]->sa_family != AF_LINK)) {
+       } else if ((info->rti_info[RTAX_IFA] != NULL) &&
+                  (info->rti_info[RTAX_IFA]->sa_family != AF_LINK)) {
                void    *addr1  = (void *)address;
-               void    *addr2  = (void *)info.rti_info[RTAX_IFA];
+               void    *addr2  = (void *)info->rti_info[RTAX_IFA];
                size_t  len     = address->sa_len;
 
-               if ((address->sa_family != info.rti_info[RTAX_IFA]->sa_family) &&
-                   (address->sa_len    != info.rti_info[RTAX_IFA]->sa_len)) {
+               if ((address->sa_family != info->rti_info[RTAX_IFA]->sa_family) &&
+                   (address->sa_len    != info->rti_info[RTAX_IFA]->sa_len)) {
                        SCLog(TRUE, LOG_NOTICE,
                              CFSTR("address family/length mismatch: %d/%d != %d/%d"),
                              address->sa_family,
                              address->sa_len,
-                             info.rti_info[RTAX_IFA]->sa_family,
-                             info.rti_info[RTAX_IFA]->sa_len);
+                             info->rti_info[RTAX_IFA]->sa_family,
+                             info->rti_info[RTAX_IFA]->sa_len);
                        goto done;
                }
 
@@ -1726,7 +1765,7 @@ checkAddress(ReachabilityStoreInfoRef     store_info,
                        case AF_INET :
                                /* ALIGN: cast ok, because only bcmp is used. */
                                addr1 = &((struct sockaddr_in *)(void *)address)->sin_addr;
-                               addr2 = &((struct sockaddr_in *)(void *)info.rti_info[RTAX_IFA])->sin_addr;
+                               addr2 = &((struct sockaddr_in *)(void *)info->rti_info[RTAX_IFA])->sin_addr;
                                len = sizeof(struct in_addr);
 
                                /*
@@ -1739,9 +1778,9 @@ checkAddress(ReachabilityStoreInfoRef     store_info,
                                }
                                break;
                        case AF_INET6 :
-                                /* ALIGN: cast ok, because only bcmp is used. */
+                               /* ALIGN: cast ok, because only bcmp is used. */
                                addr1 = &((struct sockaddr_in6 *)(void *)address)->sin6_addr;
-                               addr2 = &((struct sockaddr_in6 *)(void *)info.rti_info[RTAX_IFA])->sin6_addr;
+                               addr2 = &((struct sockaddr_in6 *)(void *)info->rti_info[RTAX_IFA])->sin6_addr;
                                len = sizeof(struct in6_addr);
                                break;
                        default :
@@ -1754,86 +1793,224 @@ checkAddress(ReachabilityStoreInfoRef  store_info,
                }
        }
 
-       if (!(info.rtm->rtm_flags & RTF_GATEWAY) &&
-           (info.rti_info[RTAX_GATEWAY] != NULL) &&
-           (info.rti_info[RTAX_GATEWAY]->sa_family == AF_LINK) &&
-           !(ifr.ifr_flags & IFF_POINTOPOINT)) {
+       if (!(info->rtm->rtm_flags & RTF_GATEWAY) &&
+           (info->rti_info[RTAX_GATEWAY] != NULL) &&
+           (info->rti_info[RTAX_GATEWAY]->sa_family == AF_LINK) &&
+           !(ifr->ifr_flags & IFF_POINTOPOINT)) {
                reach_info->flags |= kSCNetworkReachabilityFlagsIsDirect;
        }
 
-       bzero(&if_name, sizeof(if_name));
-       bcopy(info.sdl->sdl_data,
+       bzero(if_name, IFNAMSIZ);
+       bcopy(info->sdl->sdl_data,
              if_name,
-             (info.sdl->sdl_nlen <= IFNAMSIZ) ? info.sdl->sdl_nlen : IFNAMSIZ);
+             (info->sdl->sdl_nlen <= IFNAMSIZ) ? info->sdl->sdl_nlen : IFNAMSIZ);
 
        strlcpy(reach_info->if_name, if_name, sizeof(reach_info->if_name));
-       reach_info->if_index = info.sdl->sdl_index;
+       reach_info->if_index = info->sdl->sdl_index;
 
        if (_sc_debug) {
                SCLog(TRUE, LOG_INFO, CFSTR("%s  status    = %s"), log_prefix, statusMessage);
-               SCLog(TRUE, LOG_INFO, CFSTR("%s  device    = %s (%hu)"), log_prefix, if_name, info.sdl->sdl_index);
-               SCLog(TRUE, LOG_INFO, CFSTR("%s  sdl_type  = 0x%x"), log_prefix, info.sdl->sdl_type);
-               SCLog(TRUE, LOG_INFO, CFSTR("%s  ifr_flags = 0x%04hx"), log_prefix, ifr.ifr_flags);
-               SCLog(TRUE, LOG_INFO, CFSTR("%s  rtm_flags = 0x%08x"), log_prefix, info.rtm->rtm_flags);
-       }
+               SCLog(TRUE, LOG_INFO, CFSTR("%s  device    = %s (%hu)"), log_prefix, if_name, info->sdl->sdl_index);
+               SCLog(TRUE, LOG_INFO, CFSTR("%s  sdl_type  = 0x%x"), log_prefix, info->sdl->sdl_type);
+               SCLog(TRUE, LOG_INFO, CFSTR("%s  ifr_flags = 0x%04hx"), log_prefix, ifr->ifr_flags);
+               SCLog(TRUE, LOG_INFO, CFSTR("%s  rtm_flags = 0x%08x"), log_prefix, info->rtm->rtm_flags);
+       }
+done :
+       if (isock != -1) (void)close(isock);
+       return ret;
+}
+
+static Boolean
+checkAddress_with_nwi(const struct sockaddr     *address,
+                     unsigned int              if_index,
+                     ReachabilityInfo          *reach_info,
+                     const char                *log_prefix)
+{
+       route_info              info;
+       struct ifreq            ifr;
+       char                    if_name[IFNAMSIZ];
+       nwi_ifstate_t           ifstate;
+       nwi_state_t             nwi_state;
+       int                     ret;
+       int                     sc_status       = kSCStatusReachabilityUnknown;
+
+       _reach_set(reach_info, &NOT_REACHABLE, reach_info->cycle, if_index, NULL);
+
+       nwi_state = nwi_state_copy();
 
-       sc_status = kSCStatusOK;
+       if (address != NULL) {
+               ret = checkAddressRoute(address,
+                                       if_index,
+                                       if_name,
+                                       &ifr,
+                                       reach_info,
+                                       &info,
+                                       &sc_status,
+                                       log_prefix);
 
-       if (ifr.ifr_flags & IFF_POINTOPOINT) {
-               reach_info->flags |= kSCNetworkReachabilityFlagsTransientConnection;
+       }
+       else {
+               /* special case: check only for available paths off the system */
+               ret = EHOSTUNREACH;
        }
 
-       if (info.sdl->sdl_type == IFT_PPP) {
-               /*
-                * 1. check if PPP service
-                * 2. check for dial-on-demand PPP link that is not yet connected
-                * 3. get PPP server address
-                */
-               sc_status = updatePPPStatus(store_info, address, if_name, &reach_info->flags, &server, log_prefix);
-       } else if (info.sdl->sdl_type == IFT_OTHER) {
-               /*
-                * 1. check if IPSec service
-                * 2. get IPSec server address
-                */
-               sc_status = updateIPSecStatus(store_info, address, if_name, &reach_info->flags, &server, log_prefix);
+       if (ret == 0) {
+               const struct sockaddr   *vpn_server_address;
 
-#if    !TARGET_IPHONE_SIMULATOR
-               if (sc_status == kSCStatusNoKey) {
-                       /*
-                        * 1. check if VPN service
-                        * 2. get VPN server address
-                        */
-                       sc_status = updateVPNStatus(store_info, address, if_name, &reach_info->flags, &server, log_prefix);
+               sc_status = kSCStatusOK;
+
+               ifstate = nwi_state_get_ifstate(nwi_state, if_name);
+
+               if (ifstate == NULL) {
+                       goto done;
+               }
+
+               reach_info->flags |= nwi_ifstate_get_reachability_flags(ifstate);
+
+
+               vpn_server_address = nwi_ifstate_get_vpn_server(ifstate);
+               if (vpn_server_address != NULL) {
+                       char            dst_if_name[IFNAMSIZ];
+                       route_info      dst_info;
+
+                       ret = route_get(vpn_server_address, 0, &dst_info);
+                       if (ret != 0) {
+                               goto done;
+                       }
+
+                       bzero(&dst_if_name, sizeof(dst_if_name));
+                       bcopy(dst_info.sdl->sdl_data,
+                             dst_if_name,
+                             (dst_info.sdl->sdl_nlen <= IFNAMSIZ) ? dst_info.sdl->sdl_nlen : IFNAMSIZ);
+                       if (bcmp(if_name, dst_if_name, sizeof(if_name)) != 0) {
+                               nwi_ifstate_t ifstate;
+
+                               ifstate = nwi_state_get_ifstate(nwi_state, dst_if_name);
+                               if (ifstate != NULL) {
+                                       reach_info->flags |= nwi_ifstate_get_reachability_flags(ifstate);
+                               }
+                       }
+               }
+       } else if (ret == EHOSTUNREACH) {
+               if (if_index == 0) {
+                       sc_status = kSCStatusOK;
+                       reach_info->flags |= nwi_state_get_reachability_flags(nwi_state,
+                                                                             (address != NULL) ? address->sa_family
+                                                                             : AF_UNSPEC);
+               } else {
+                       // if scoped request
+                       sc_status = kSCStatusNoKey;
                }
-#endif // !TARGET_IPHONE_SIMULATOR
+
+       }
+
+done:
+       if (reach_info->flags == 0) {
+               SCLog(_sc_debug, LOG_INFO, CFSTR("%s  cannot be reached"), log_prefix);
+       }
+
+       if (nwi_state != NULL) {
+               nwi_state_release(nwi_state);
+       }
+
+       if ((sc_status != kSCStatusOK) && (sc_status != kSCStatusNoKey)) {
+               _SCErrorSet(sc_status);
+               return FALSE;
        }
 
+       return TRUE;
+}
+
 
-       goto done;
+static Boolean
+checkAddress_bypass_nwi(ReachabilityStoreInfoRef       store_info,
+                       const struct sockaddr           *address,
+                       unsigned int                    if_index,
+                       ReachabilityInfo                *reach_info,
+                       const char                      *log_prefix)
+{
+       route_info              info;
+       struct ifreq            ifr;
+       char                    if_name[IFNAMSIZ];
+       int                     ret;
+       CFStringRef             server = NULL;
+       int                     sc_status       = kSCStatusReachabilityUnknown;
 
-    checkAvailable :
+       _reach_set(reach_info, &NOT_REACHABLE, reach_info->cycle, if_index, NULL);
 
+       if (address != NULL) {
+               ret = checkAddressRoute(address,
+                                       if_index,
+                                       if_name,
+                                       &ifr,
+                                       reach_info,
+                                       &info,
+                                       &sc_status,
+                                       log_prefix);
 
-       sc_status = updatePPPAvailable(store_info, address, &reach_info->flags, log_prefix);
-       if ((sc_status == kSCStatusOK) && (reach_info->flags != 0)) {
-               goto done;
+       }
+       else {
+               /* special case: check only for available paths off the system */
+               ret = EHOSTUNREACH;
        }
 
-#if    !TARGET_IPHONE_SIMULATOR
-       sc_status = updateVPNAvailable(store_info, address, &reach_info->flags, log_prefix);
-       if ((sc_status == kSCStatusOK) && (reach_info->flags != 0)) {
-               goto done;
+       if (ret == 0) {
+               sc_status = kSCStatusOK;
+
+               if (ifr.ifr_flags & IFF_POINTOPOINT) {
+                       reach_info->flags |= kSCNetworkReachabilityFlagsTransientConnection;
+               }
+
+               if (info.sdl->sdl_type == IFT_PPP) {
+                       /*
+                        * 1. check if PPP service
+                        * 2. check for dial-on-demand PPP link that is not yet connected
+                        * 3. get PPP server address
+                        */
+                       sc_status = updatePPPStatus(store_info, address, if_name, &reach_info->flags, &server, log_prefix);
+               } else if (info.sdl->sdl_type == IFT_OTHER) {
+                       /*
+                        * 1. check if IPSec service
+                        * 2. get IPSec server address
+                        */
+                       sc_status = updateIPSecStatus(store_info, address, if_name, &reach_info->flags, &server, log_prefix);
+                       if (sc_status == kSCStatusNoKey) {
+                               /*
+                                * 1. check if VPN service
+                                * 2. get VPN server address
+                                */
+                               sc_status = updateVPNStatus(store_info, address, if_name, &reach_info->flags, &server, log_prefix);
+                       }
+               }
+
+       } else if (ret == EHOSTUNREACH) {
+               if (if_index != 0) {
+                       // if scoped request
+                       sc_status = kSCStatusNoKey;
+                       goto done;
+               }
+
+
+               sc_status = updatePPPAvailable(store_info, address, &reach_info->flags, log_prefix);
+               if ((sc_status == kSCStatusOK) && (reach_info->flags != 0)) {
+                       goto done;
+               }
+
+               sc_status = updateVPNAvailable(store_info, address, &reach_info->flags, log_prefix);
+               if ((sc_status == kSCStatusOK) && (reach_info->flags != 0)) {
+                       goto done;
+               }
+
        }
-#endif // !TARGET_IPHONE_SIMULATOR
 
-    done :
+done :
 
        if (reach_info->flags == 0) {
                SCLog(_sc_debug, LOG_INFO, CFSTR("%s  cannot be reached"), log_prefix);
        }
 
-       if (isock != -1)        (void)close(isock);
        if (server != NULL)     CFRelease(server);
+
        if ((sc_status != kSCStatusOK) && (sc_status != kSCStatusNoKey)) {
                _SCErrorSet(sc_status);
                return FALSE;
@@ -1843,6 +2020,28 @@ checkAddress(ReachabilityStoreInfoRef    store_info,
 }
 
 
+static inline Boolean
+checkAddress(ReachabilityStoreInfoRef  store_info,
+            const struct sockaddr      *address,
+            unsigned int               if_index,
+            ReachabilityInfo           *reach_info,
+            const char                 *log_prefix)
+{
+       if (!D_nwiBypass) {
+               return (checkAddress_with_nwi(address,
+                                             if_index,
+                                             reach_info,
+                                             log_prefix));
+
+       }
+
+       return (checkAddress_bypass_nwi(store_info,
+                                       address,
+                                       if_index,
+                                       reach_info,
+                                       log_prefix));
+}
+
 #pragma mark -
 #pragma mark SCNetworkReachability APIs
 
@@ -1883,14 +2082,7 @@ _SCNetworkReachabilityCopyTargetDescription(SCNetworkReachabilityRef target)
                        break;
                }
                case reachabilityTypeName : {
-                       if ((targetPrivate->name != NULL)) {
-                               CFStringAppendFormat(str, NULL, CFSTR("name = %s"), targetPrivate->name);
-                       }
-                       if ((targetPrivate->serv != NULL)) {
-                               CFStringAppendFormat(str, NULL, CFSTR("%sserv = %s"),
-                                                    targetPrivate->name != NULL ? ", " : "",
-                                                    targetPrivate->serv);
-                       }
+                       CFStringAppendFormat(str, NULL, CFSTR("name = %s"), targetPrivate->name);
                        break;
                }
        }
@@ -1908,7 +2100,7 @@ _SCNetworkReachabilityCopyTargetFlags(SCNetworkReachabilityRef target)
 
        str = CFStringCreateWithFormat(allocator,
                                       NULL,
-                                      CFSTR("flags = 0x%08x, if_index = %hu%s"),
+                                      CFSTR("flags = 0x%08x, if_index = %u%s"),
                                       targetPrivate->info.flags,
                                       targetPrivate->info.if_index,
                                       targetPrivate->info.sleeping ? ", z" : "");
@@ -1935,15 +2127,20 @@ __SCNetworkReachabilityCopyDescription(CFTypeRef cf)
 
        // add additional "name" info
        if (targetPrivate->type == reachabilityTypeName) {
-               if (targetPrivate->dnsMP != MACH_PORT_NULL) {
+               if (targetPrivate->dnsActive) {
                        CFStringAppendFormat(result, NULL, CFSTR(" (DNS query active)"));
-               } else if (targetPrivate->dnsRetry != NULL) {
-                       CFStringAppendFormat(result, NULL, CFSTR(" (DNS retry queued)"));
-               } else if ((targetPrivate->resolvedAddress != NULL) || (targetPrivate->resolvedAddressError != NETDB_SUCCESS)) {
-                       if (targetPrivate->resolvedAddress != NULL) {
-                               if (isA_CFArray(targetPrivate->resolvedAddress)) {
+#ifdef HAVE_REACHABILITY_SERVER
+               } else if (targetPrivate->serverActive &&
+                          (targetPrivate->info.flags & kSCNetworkReachabilityFlagsFirstResolvePending)) {
+                       CFStringAppendFormat(result, NULL, CFSTR(" (server query active)"));
+#endif // HAVE_REACHABILITY_SERVER
+               } else if (targetPrivate->dnsMP != MACH_PORT_NULL) {
+                       CFStringAppendFormat(result, NULL, CFSTR(" (DNS* query active)"));
+               } else if ((targetPrivate->resolvedAddresses != NULL) || (targetPrivate->resolvedError != NETDB_SUCCESS)) {
+                       if (targetPrivate->resolvedAddresses != NULL) {
+                               if (isA_CFArray(targetPrivate->resolvedAddresses)) {
                                        CFIndex i;
-                                       CFIndex n       = CFArrayGetCount(targetPrivate->resolvedAddress);
+                                       CFIndex n       = CFArrayGetCount(targetPrivate->resolvedAddresses);
 
                                        CFStringAppendFormat(result, NULL, CFSTR(" ("));
                                        for (i = 0; i < n; i++) {
@@ -1951,31 +2148,38 @@ __SCNetworkReachabilityCopyDescription(CFTypeRef cf)
                                                char            buf[64];
                                                struct sockaddr *sa;
 
-                                               address = CFArrayGetValueAtIndex(targetPrivate->resolvedAddress, i);
+                                               address = CFArrayGetValueAtIndex(targetPrivate->resolvedAddresses, i);
                                                sa      = (struct sockaddr *)CFDataGetBytePtr(address);
                                                _SC_sockaddr_to_string(sa, buf, sizeof(buf));
                                                CFStringAppendFormat(result, NULL, CFSTR("%s%s"),
                                                                     i > 0 ? ", " : "",
                                                                     buf);
                                        }
-                               } else if (CFEqual(targetPrivate->resolvedAddress, kCFNull)) {
-                                       CFStringAppendFormat(result, NULL, CFSTR(" (%s"),
-                                                            gai_strerror(targetPrivate->resolvedAddressError));
+                                       CFStringAppendFormat(result, NULL, CFSTR(")"));
+                               } else if (CFEqual(targetPrivate->resolvedAddresses, kCFNull)) {
+                                       CFStringAppendFormat(result, NULL, CFSTR(" (%s)"),
+                                                            gai_strerror(targetPrivate->resolvedError));
                                } else {
-                                       CFStringAppendFormat(result, NULL, CFSTR(" (no addresses"));
+                                       CFStringAppendFormat(result, NULL, CFSTR(" (no addresses)"));
                                }
                        } else {
-                               CFStringAppendFormat(result, NULL, CFSTR(" (%s"),
-                                                    gai_strerror(targetPrivate->resolvedAddressError));
-                       }
-                       if (targetPrivate->llqActive) {
-                               CFStringAppendFormat(result, NULL, CFSTR("), DNS llq active"));
-                       } else {
-                               CFStringAppendFormat(result, NULL, CFSTR(")"));
+                               CFStringAppendFormat(result, NULL, CFSTR(" (%s)"),
+                                                    gai_strerror(targetPrivate->resolvedError));
                        }
-               } else if (targetPrivate->llqActive) {
-                       CFStringAppendFormat(result, NULL, CFSTR(" (DNS llq active)"));
                }
+               if (targetPrivate->dnsFlags != 0) {
+                       CFStringAppendFormat(result, NULL, CFSTR(", " DNS_FLAGS_FORMAT),
+                                            DNS_FLAGS_VALUES(targetPrivate));
+               }
+       }
+
+       if (targetPrivate->onDemandBypass) {
+               CFStringAppendFormat(result, NULL, CFSTR(", !ondemand"));
+       }
+
+
+       if (targetPrivate->resolverBypass) {
+               CFStringAppendFormat(result, NULL, CFSTR(", !resolve"));
        }
 
 
@@ -2016,11 +2220,8 @@ __SCNetworkReachabilityDeallocate(CFTypeRef cf)
        if (targetPrivate->name != NULL)
                CFAllocatorDeallocate(NULL, (void *)targetPrivate->name);
 
-       if (targetPrivate->serv != NULL)
-               CFAllocatorDeallocate(NULL, (void *)targetPrivate->serv);
-
-       if (targetPrivate->resolvedAddress != NULL)
-               CFRelease(targetPrivate->resolvedAddress);
+       if (targetPrivate->resolvedAddresses != NULL)
+               CFRelease(targetPrivate->resolvedAddresses);
 
        if (targetPrivate->localAddress != NULL)
                CFAllocatorDeallocate(NULL, (void *)targetPrivate->localAddress);
@@ -2081,11 +2282,6 @@ __SCNetworkReachabilityInitialize(void)
                _sc_debug = TRUE;
        }
 
-       // set per-process "bypass" of the SCNetworkReachability server
-       if (getenv("LONG_LIVED_QUERY_BYPASS") != NULL) {
-               D_llqBypass = TRUE;
-       }
-
 #ifdef HAVE_REACHABILITY_SERVER
        // set per-process "bypass" of the SCNetworkReachability server
        if (getenv("REACH_SERVER_BYPASS") != NULL) {
@@ -2093,6 +2289,11 @@ __SCNetworkReachabilityInitialize(void)
        }
 #endif // HAVE_REACHABILITY_SERVER
 
+
+       if (getenv("NWI_BYPASS") != NULL) {
+               D_nwiBypass = TRUE;
+       }
+
        pthread_mutexattr_init(&lock_attr);
        pthread_mutexattr_settype(&lock_attr, PTHREAD_MUTEX_ERRORCHECK);
 
@@ -2118,26 +2319,22 @@ __SCNetworkReachability_concurrent_queue()
 
 
 /*
- * __SCNetworkReachabilityPerformInlineNoLock
+ * __SCNetworkReachabilityPerformConcurrent
  *
  * Calls reachPerform()
  * - caller must be holding a reference to the target
  * - caller must *not* be holding the target lock
  * - caller must be running on the __SCNetworkReachability_concurrent_queue()
  */
-static __inline__ void
-__SCNetworkReachabilityPerformInlineNoLock(SCNetworkReachabilityRef target, Boolean needResolve)
+__private_extern__
+void
+__SCNetworkReachabilityPerformConcurrent(SCNetworkReachabilityRef target)
 {
        dispatch_queue_t                queue;
        SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
 
        MUTEX_LOCK(&targetPrivate->lock);
 
-       if (needResolve) {
-               // allow the DNS query to be [re-]started
-               targetPrivate->needResolve = TRUE;
-       }
-
        queue = targetPrivate->dispatchQueue;
        if (queue != NULL) {
                dispatch_group_t        group;
@@ -2167,71 +2364,36 @@ __SCNetworkReachabilityPerformInlineNoLock(SCNetworkReachabilityRef target, Bool
 }
 
 
-#ifdef HAVE_REACHABILITY_SERVER
 /*
- * __SCNetworkReachabilityPerformNoLock
+ * __SCNetworkReachabilityPerform
  *
  * Calls reachPerform()
- * - caller must *not* be holding the target lock
- * - caller must *not* running on the __SCNetworkReachability_concurrent_queue()
+ * - caller can be holding the target lock
+ * - caller can be running on any dispatch queue
  */
 __private_extern__
 void
-__SCNetworkReachabilityPerformNoLock(SCNetworkReachabilityRef target)
+__SCNetworkReachabilityPerform(SCNetworkReachabilityRef target)
 {
        CFRetain(target);
        dispatch_async(__SCNetworkReachability_concurrent_queue(), ^{
-               __SCNetworkReachabilityPerformInlineNoLock(target, FALSE);
+               __SCNetworkReachabilityPerformConcurrent(target);
                CFRelease(target);
        });
 
        return;
 }
-#endif // HAVE_REACHABILITY_SERVER
-
-
-/*
- * __SCNetworkReachabilityPerformConcurrent
- *
- * Calls reachPerform()
- * - caller must be holding the target lock
- * - caller running on the __SCNetworkReachability_concurrent_queue()
- */
-static __inline__ void
-__SCNetworkReachabilityPerformConcurrent(SCNetworkReachabilityRef target)
-{
-       dispatch_queue_t                queue;
-       SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
-
-       MUTEX_ASSERT_HELD(&targetPrivate->lock);
-
-       queue = targetPrivate->dispatchQueue;
-       if (queue != NULL) {
-               CFRetain(target);
-               dispatch_group_async(targetPrivate->dispatchGroup, queue, ^{
-                       reachPerform((void *)target);
-                       CFRelease(target);
-               });
-       } else {
-               if (targetPrivate->rls != NULL) {
-                       CFRunLoopSourceSignal(targetPrivate->rls);
-                       _SC_signalRunLoop(target, targetPrivate->rls, targetPrivate->rlList);
-               }
-       }
-
-       return;
-}
 
 
 /*
- * __SCNetworkReachabilityPerform
+ * __SCNetworkReachabilityPerformLocked
  *
  * Calls reachPerform()
  * - caller must be holding the target lock
  * - caller not running on the __SCNetworkReachability_concurrent_queue()
  */
 static void
-__SCNetworkReachabilityPerform(SCNetworkReachabilityRef target)
+__SCNetworkReachabilityPerformLocked(SCNetworkReachabilityRef target)
 {
        dispatch_queue_t                queue;
        SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
@@ -2277,79 +2439,18 @@ __SCNetworkReachabilityCreatePrivate(CFAllocatorRef     allocator)
                return NULL;
        }
 
+       bzero((void *)targetPrivate + sizeof(CFRuntimeBase), size);
+
        MUTEX_INIT(&targetPrivate->lock);
 
-       targetPrivate->name                             = NULL;
-       targetPrivate->serv                             = NULL;
-       targetPrivate->hints                            = HINTS_DEFAULT;
-       targetPrivate->needResolve                      = FALSE;
-       targetPrivate->resolvedAddress                  = NULL;
-       targetPrivate->resolvedAddressError             = NETDB_SUCCESS;
+       targetPrivate->cycle                            = 1;
+       targetPrivate->last_notify                      = NOT_REPORTED;
 
-       targetPrivate->if_index                         = 0;
+#ifdef HAVE_REACHABILITY_SERVER
+       targetPrivate->serverBypass                     = D_serverBypass;
+#endif // HAVE_REACHABILITY_SERVER
 
-       targetPrivate->localAddress                     = NULL;
-       targetPrivate->remoteAddress                    = NULL;
 
-       targetPrivate->cycle                            = 1;
-       targetPrivate->info                             = NOT_REACHABLE;
-       targetPrivate->last_notify                      = NOT_REPORTED;
-
-       targetPrivate->scheduled                        = FALSE;
-       targetPrivate->rls                              = NULL;
-       targetPrivate->rlsFunction                      = NULL;
-       targetPrivate->rlsContext.info                  = NULL;
-       targetPrivate->rlsContext.retain                = NULL;
-       targetPrivate->rlsContext.release               = NULL;
-       targetPrivate->rlsContext.copyDescription       = NULL;
-       targetPrivate->rlList                           = NULL;
-
-       targetPrivate->haveDNS                          = FALSE;
-       targetPrivate->dnsMP                            = MACH_PORT_NULL;
-       targetPrivate->dnsPort                          = NULL;
-       targetPrivate->dnsRLS                           = NULL;
-       targetPrivate->dnsSource                        = NULL;
-       targetPrivate->dnsQueryStart                    = TIME_ZERO;
-       targetPrivate->dnsQueryEnd                      = TIME_ZERO;
-       targetPrivate->dnsRetry                         = NULL;
-       targetPrivate->dnsRetryCount                    = 0;
-
-       targetPrivate->last_dns                         = TIME_ZERO;
-       targetPrivate->last_network                     = TIME_ZERO;
-#if    !TARGET_OS_IPHONE
-       targetPrivate->last_power                       = TIME_ZERO;
-#endif // !TARGET_OS_IPHONE
-       targetPrivate->last_push                        = TIME_ZERO;
-
-       targetPrivate->onDemandBypass                   = FALSE;
-       targetPrivate->onDemandName                     = NULL;
-       targetPrivate->onDemandRemoteAddress            = NULL;
-       targetPrivate->onDemandServer                   = NULL;
-       targetPrivate->onDemandServiceID                = NULL;
-
-#ifdef HAVE_REACHABILITY_SERVER
-       targetPrivate->serverBypass                     = D_serverBypass;
-#endif // HAVE_REACHABILITY_SERVER
-
-
-       targetPrivate->llqActive                        = FALSE;
-       targetPrivate->llqBypass                        = D_llqBypass;
-       targetPrivate->llqTarget                        = NULL;
-       targetPrivate->llqTimer                         = NULL;
-
-#ifdef HAVE_REACHABILITY_SERVER
-       targetPrivate->serverActive                     = FALSE;
-       targetPrivate->serverScheduled                  = FALSE;
-       targetPrivate->serverInfo                       = NOT_REACHABLE;
-
-       targetPrivate->serverDigest                     = NULL;
-       targetPrivate->serverGroup                      = NULL;
-       targetPrivate->serverInfoValid                  = FALSE;
-       targetPrivate->serverQueryActive                = 0;
-       targetPrivate->serverQueue                      = NULL;
-       targetPrivate->serverReferences                 = 0;
-       targetPrivate->serverWatchers                   = NULL;
-#endif // HAVE_REACHABILITY_SERVER
 
        targetPrivate->log_prefix[0] = '\0';
        if (_sc_log > 0) {
@@ -2412,6 +2513,8 @@ is_valid_address(const struct sockaddr *address)
 }
 
 
+
+
 SCNetworkReachabilityRef
 SCNetworkReachabilityCreateWithAddress(CFAllocatorRef          allocator,
                                       const struct sockaddr    *address)
@@ -2433,6 +2536,7 @@ SCNetworkReachabilityCreateWithAddress(CFAllocatorRef             allocator,
        targetPrivate->remoteAddress = CFAllocatorAllocate(NULL, address->sa_len, 0);
        bcopy(address, targetPrivate->remoteAddress, address->sa_len);
 
+
        SCLog((_sc_debug && (_sc_log > 0)), LOG_INFO, CFSTR("%s%s %@"),
              targetPrivate->log_prefix,
              DEBUG_REACHABILITY_TYPE_ADDRESS,
@@ -2487,6 +2591,7 @@ SCNetworkReachabilityCreateWithAddressPair(CFAllocatorRef         allocator,
                bcopy(remoteAddress, targetPrivate->remoteAddress, remoteAddress->sa_len);
        }
 
+
        SCLog((_sc_debug && (_sc_log > 0)), LOG_INFO, CFSTR("%s%s %@"),
              targetPrivate->log_prefix,
              DEBUG_REACHABILITY_TYPE_ADDRESSPAIR,
@@ -2500,6 +2605,9 @@ SCNetworkReachabilityRef
 SCNetworkReachabilityCreateWithName(CFAllocatorRef     allocator,
                                    const char          *nodename)
 {
+#ifdef HAVE_REACHABILITY_SERVER
+       CFDictionaryRef                 appLayerVPNProperties;
+#endif // HAVE_REACHABILITY_SERVER
        union {
                struct sockaddr         sa;
                struct sockaddr_in      sin;
@@ -2538,6 +2646,14 @@ SCNetworkReachabilityCreateWithName(CFAllocatorRef       allocator,
        targetPrivate->info.flags |= kSCNetworkReachabilityFlagsFirstResolvePending;
 #ifdef HAVE_REACHABILITY_SERVER
        targetPrivate->serverInfo.flags |= kSCNetworkReachabilityFlagsFirstResolvePending;
+
+       /* make sure AppLayerVPN only is in client mode */
+       appLayerVPNProperties = VPNAppLayerCopyCurrentAppProperties();
+       if (appLayerVPNProperties != NULL) {
+               targetPrivate->useVPNAppLayer = TRUE;
+               targetPrivate->serverBypass = YES;
+               CFRelease(appLayerVPNProperties);
+       }
 #endif // HAVE_REACHABILITY_SERVER
 
        SCLog((_sc_debug && (_sc_log > 0)), LOG_INFO, CFSTR("%s%s %@"),
@@ -2558,16 +2674,13 @@ SCNetworkReachabilityCreateWithOptions(CFAllocatorRef   allocator,
        const struct sockaddr           *addr_l         = NULL;
        const struct sockaddr           *addr_r         = NULL;
        CFDataRef                       data;
-       struct addrinfo                 *hints          = NULL;
        CFStringRef                     interface       = NULL;
-       CFBooleanRef                    llqBypass;
        CFStringRef                     nodename;
        CFBooleanRef                    onDemandBypass;
        CFBooleanRef                    resolverBypass;
 #ifdef HAVE_REACHABILITY_SERVER
        CFBooleanRef                    serverBypass;
 #endif // HAVE_REACHABILITY_SERVER
-       CFStringRef                     servname;
        SCNetworkReachabilityRef        target;
        SCNetworkReachabilityPrivateRef targetPrivate;
 
@@ -2582,12 +2695,6 @@ SCNetworkReachabilityCreateWithOptions(CFAllocatorRef    allocator,
                _SCErrorSet(kSCStatusInvalidArgument);
                return NULL;
        }
-       servname = CFDictionaryGetValue(options, kSCNetworkReachabilityOptionServName);
-       if ((servname != NULL) &&
-           (!isA_CFString(servname) || (CFStringGetLength(servname) == 0))) {
-               _SCErrorSet(kSCStatusInvalidArgument);
-               return NULL;
-       }
        data = CFDictionaryGetValue(options, kSCNetworkReachabilityOptionLocalAddress);
        if (data != NULL) {
                if (!isA_CFData(data) || (CFDataGetLength(data) < sizeof(struct sockaddr_in))) {
@@ -2604,23 +2711,6 @@ SCNetworkReachabilityCreateWithOptions(CFAllocatorRef    allocator,
                }
                addr_r = (const struct sockaddr *)CFDataGetBytePtr(data);
        }
-       data = CFDictionaryGetValue(options, kSCNetworkReachabilityOptionHints);
-       if (data != NULL) {
-               if (!isA_CFData(data) || (CFDataGetLength(data) != sizeof(targetPrivate->hints))) {
-                       _SCErrorSet(kSCStatusInvalidArgument);
-                       return NULL;
-               }
-
-               /* ALIGN: CF aligns to >8 byte boundries */
-               hints = (struct addrinfo *)(void *)CFDataGetBytePtr(data);
-               if ((hints->ai_addrlen   != 0)    ||
-                   (hints->ai_addr      != NULL) ||
-                   (hints->ai_canonname != NULL) ||
-                   (hints->ai_next      != NULL)) {
-                       _SCErrorSet(kSCStatusInvalidArgument);
-                       return NULL;
-               }
-       }
        interface = CFDictionaryGetValue(options, kSCNetworkReachabilityOptionInterface);
        if ((interface != NULL) &&
            (!isA_CFString(interface) || (CFStringGetLength(interface) == 0))) {
@@ -2639,12 +2729,6 @@ SCNetworkReachabilityCreateWithOptions(CFAllocatorRef    allocator,
        }
 
 
-       llqBypass = CFDictionaryGetValue(options, kSCNetworkReachabilityOptionLongLivedQueryBypass);
-       if ((llqBypass != NULL) && !isA_CFBoolean(llqBypass)) {
-               _SCErrorSet(kSCStatusInvalidArgument);
-               return NULL;
-       }
-
 #ifdef HAVE_REACHABILITY_SERVER
        serverBypass = CFDictionaryGetValue(options, kSCNetworkReachabilityOptionServerBypass);
        if ((serverBypass != NULL) && !isA_CFBoolean(serverBypass)) {
@@ -2653,11 +2737,12 @@ SCNetworkReachabilityCreateWithOptions(CFAllocatorRef   allocator,
        }
 #endif // HAVE_REACHABILITY_SERVER
 
-       if ((nodename != NULL) || (servname != NULL)) {
+
+       if (nodename != NULL) {
                const char      *name;
 
                if ((addr_l != NULL) || (addr_r != NULL)) {
-                       // can't have both a name/serv and an address
+                       // can't have both a nodename and an address
                        _SCErrorSet(kSCStatusInvalidArgument);
                        return NULL;
                }
@@ -2671,7 +2756,7 @@ SCNetworkReachabilityCreateWithOptions(CFAllocatorRef     allocator,
                } else if (addr_r != NULL) {
                        target = SCNetworkReachabilityCreateWithAddress(NULL, addr_r);
                } else if (addr_l != NULL) {
-                       target = SCNetworkReachabilityCreateWithAddress(NULL, addr_l);
+                       target = SCNetworkReachabilityCreateWithAddressPair(NULL, addr_l, NULL);
                } else {
                        _SCErrorSet(kSCStatusInvalidArgument);
                        return NULL;
@@ -2682,14 +2767,6 @@ SCNetworkReachabilityCreateWithOptions(CFAllocatorRef    allocator,
        }
 
        targetPrivate = (SCNetworkReachabilityPrivateRef)target;
-       if (targetPrivate->type == reachabilityTypeName) {
-               if (servname != NULL) {
-                       targetPrivate->serv = _SC_cfstring_to_cstring(servname, NULL, 0, kCFStringEncodingUTF8);
-               }
-               if (hints != NULL) {
-                       bcopy(hints, &targetPrivate->hints, sizeof(targetPrivate->hints));
-               }
-       }
 
        if (interface != NULL) {
                if ((_SC_cfstring_to_cstring(interface,
@@ -2704,10 +2781,6 @@ SCNetworkReachabilityCreateWithOptions(CFAllocatorRef    allocator,
        }
 
 
-       if (llqBypass != NULL) {
-               targetPrivate->llqBypass = CFBooleanGetValue(llqBypass);
-       }
-
        if (onDemandBypass != NULL) {
                targetPrivate->onDemandBypass = CFBooleanGetValue(onDemandBypass);
        }
@@ -2717,11 +2790,13 @@ SCNetworkReachabilityCreateWithOptions(CFAllocatorRef   allocator,
        }
 
 #ifdef HAVE_REACHABILITY_SERVER
-       if (serverBypass != NULL) {
+       /* if by name, make sure AppLayerVPN only is in client mode */
+       if (serverBypass != NULL && targetPrivate->useVPNAppLayer == FALSE) {
                targetPrivate->serverBypass = CFBooleanGetValue(serverBypass);
        }
 #endif // HAVE_REACHABILITY_SERVER
 
+
        if (_sc_debug && (_sc_log > 0)) {
                const char      *opt;
 
@@ -2775,12 +2850,12 @@ SCNetworkReachabilityCopyResolvedAddress(SCNetworkReachabilityRef       target,
        }
 
        if (error_num) {
-               *error_num = targetPrivate->resolvedAddressError;
+               *error_num = targetPrivate->resolvedError;
        }
 
-       if (targetPrivate->resolvedAddress != NULL) {
-               if (isA_CFArray(targetPrivate->resolvedAddress)) {
-                       return CFRetain(targetPrivate->resolvedAddress);
+       if (targetPrivate->resolvedAddresses != NULL) {
+               if (isA_CFArray(targetPrivate->resolvedAddresses)) {
+                       return CFRetain(targetPrivate->resolvedAddresses);
                } else {
                        /* if status is known but no resolved addresses to return */
                        _SCErrorSet(kSCStatusOK);
@@ -2794,18 +2869,18 @@ SCNetworkReachabilityCopyResolvedAddress(SCNetworkReachabilityRef       target,
 
 
 static void
-__SCNetworkReachabilitySetResolvedAddress(int32_t                      status,
-                                         struct addrinfo               *res,
-                                         SCNetworkReachabilityRef      target)
+__SCNetworkReachabilitySetResolvedAddresses(int32_t                    status,
+                                           struct addrinfo             *res,
+                                           SCNetworkReachabilityRef    target)
 {
        struct addrinfo                         *resP;
        SCNetworkReachabilityPrivateRef         targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
 
        MUTEX_ASSERT_HELD(&targetPrivate->lock);
 
-       if (targetPrivate->resolvedAddress != NULL) {
-               CFRelease(targetPrivate->resolvedAddress);
-               targetPrivate->resolvedAddress = NULL;
+       if (targetPrivate->resolvedAddresses != NULL) {
+               CFRelease(targetPrivate->resolvedAddresses);
+               targetPrivate->resolvedAddresses = NULL;
        }
 
        if ((status == 0) && (res != NULL)) {
@@ -2827,23 +2902,23 @@ __SCNetworkReachabilitySetResolvedAddress(int32_t                       status,
                }
 
                /* save the resolved address[es] */
-               targetPrivate->resolvedAddress      = addresses;
-               targetPrivate->resolvedAddressError = NETDB_SUCCESS;
+               targetPrivate->resolvedAddresses = addresses;
+               targetPrivate->resolvedError     = NETDB_SUCCESS;
        } else {
                SCLog(_sc_debug, LOG_INFO, CFSTR("%sgetaddrinfo() failed: %s"),
                      targetPrivate->log_prefix,
                      gai_strerror(status));
 
                /* save the error associated with the attempt to resolve the name */
-               targetPrivate->resolvedAddress      = CFRetain(kCFNull);
-               targetPrivate->resolvedAddressError = status;
+               targetPrivate->resolvedAddresses = CFRetain(kCFNull);
+               targetPrivate->resolvedError     = status;
        }
        targetPrivate->needResolve = FALSE;
 
        if (res != NULL)        freeaddrinfo(res);
 
        if (targetPrivate->scheduled) {
-               __SCNetworkReachabilityPerform(target);
+               __SCNetworkReachabilityPerformLocked(target);
        }
 
        return;
@@ -2851,18 +2926,18 @@ __SCNetworkReachabilitySetResolvedAddress(int32_t                       status,
 
 
 static void
-__SCNetworkReachabilityCallbackSetResolvedAddress(int32_t status, struct addrinfo *res, void *context)
+__SCNetworkReachabilityCallbackSetResolvedAddresses(int32_t status, struct addrinfo *res, void *context)
 {
        SCNetworkReachabilityRef        target          = (SCNetworkReachabilityRef)context;
        SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
 
-       __dns_query_end(target,
-                       ((status == 0) && (res != NULL)),       // if successful query
-                       dns_query_async,                        // async
-                       &targetPrivate->dnsQueryStart,          // start time
-                       &targetPrivate->dnsQueryEnd);           // end time
+       __mark_operation_end(target,
+                            ((status == 0) && (res != NULL)),  // if successful query
+                            dns_query_async,                   // async
+                            &targetPrivate->dnsQueryStart,     // start time
+                            &targetPrivate->dnsQueryEnd);      // end time
 
-       __SCNetworkReachabilitySetResolvedAddress(status, res, target);
+       __SCNetworkReachabilitySetResolvedAddresses(status, res, target);
        return;
 }
 
@@ -2896,12 +2971,8 @@ replyMPCopyDescription(const void *info)
 
        return CFStringCreateWithFormat(NULL,
                                        NULL,
-                                       CFSTR("<getaddrinfo_async_start reply MP> {%s%s%s%s%s, target = %p}"),
-                                       targetPrivate->name != NULL ? "name = " : "",
-                                       targetPrivate->name != NULL ? targetPrivate->name : "",
-                                       targetPrivate->name != NULL && targetPrivate->serv != NULL ? ", " : "",
-                                       targetPrivate->serv != NULL ? "serv = " : "",
-                                       targetPrivate->serv != NULL ? targetPrivate->serv : "",
+                                       CFSTR("<getaddrinfo_async_start reply MP> {name = %s, target = %p}"),
+                                       targetPrivate->name,
                                        target);
 }
 
@@ -2984,11 +3055,11 @@ enqueueAsyncDNSQuery_dispatch(SCNetworkReachabilityRef target)
        });
 
        dispatch_source_set_cancel_handler(source, ^{
-#if    !TARGET_OS_EMBEDDED
+#if    !TARGET_OS_IPHONE
                mach_vm_address_t       context;
-#else  // !TARGET_OS_EMBEDDED
+#else  // !TARGET_OS_IPHONE
                mach_port_context_t     context;
-#endif // !TARGET_OS_EMBEDDED
+#endif // !TARGET_OS_IPHONE
                kern_return_t           kr;
                mach_port_t             mp;
 
@@ -3084,7 +3155,7 @@ enqueueAsyncDNSQuery_CF(SCNetworkReachabilityRef target)
 
 
 static Boolean
-enqueueAsyncDNSQuery(SCNetworkReachabilityRef target, mach_port_t mp)
+requeueAsyncDNSQuery(SCNetworkReachabilityRef target, mach_port_t mp)
 {
        Boolean                         ok              = FALSE;
        SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
@@ -3109,6 +3180,50 @@ enqueueAsyncDNSQuery(SCNetworkReachabilityRef target, mach_port_t mp)
 }
 
 
+static Boolean
+enqueueAsyncDNSQuery(SCNetworkReachabilityRef target)
+{
+       int                             error   = 0;
+       mach_port_t                     mp      = MACH_PORT_NULL;
+       Boolean                         ok;
+       SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
+
+       // track the DNS resolution time
+       __mark_operation_start(&targetPrivate->dnsQueryStart, &targetPrivate->dnsQueryEnd);
+
+#ifdef HAVE_GETADDRINFO_INTERFACE_ASYNC_CALL
+       if (targetPrivate->if_index == 0) {
+#endif // HAVE_GETADDRINFO_INTERFACE_ASYNC_CALL
+               error = getaddrinfo_async_start(&mp,
+                                               targetPrivate->name,
+                                               NULL,
+                                               &HINTS_DEFAULT,
+                                               __SCNetworkReachabilityCallbackSetResolvedAddresses,
+                                               (void *)target);
+#ifdef HAVE_GETADDRINFO_INTERFACE_ASYNC_CALL
+       } else {
+               mp = _getaddrinfo_interface_async_call(targetPrivate->name,
+                                                      NULL,
+                                                      &HINTS_DEFAULT,
+                                                      targetPrivate->if_name,
+                                                      __SCNetworkReachabilityCallbackSetResolvedAddresses,
+                                                      (void *)target);
+               if (mp == MACH_PORT_NULL) {
+                       error = EAI_SYSTEM;
+               }
+       }
+#endif // HAVE_GETADDRINFO_INTERFACE_ASYNC_CALL
+       if (error != 0) {
+               /* save the error associated with the attempt to resolve the name */
+               __SCNetworkReachabilityCallbackSetResolvedAddresses(error, NULL, (void *)target);
+               return FALSE;
+       }
+
+       ok = requeueAsyncDNSQuery(target, mp);
+       return ok;
+}
+
+
 static void
 dequeueAsyncDNSQuery(SCNetworkReachabilityRef target, Boolean cancel)
 {
@@ -3166,13 +3281,13 @@ getaddrinfo_async_handleCFReply(CFMachPortRef port, void *msg, CFIndex size, voi
        dequeueAsyncDNSQuery(target, FALSE);
        status = getaddrinfo_async_handle_reply(msg);
        if ((status == 0) &&
-           (targetPrivate->resolvedAddress == NULL) && (targetPrivate->resolvedAddressError == NETDB_SUCCESS)) {
+           (targetPrivate->resolvedAddresses == NULL) && (targetPrivate->resolvedError == NETDB_SUCCESS)) {
                Boolean ok;
 
                // if the request is not complete and needs to be re-queued
-               ok = enqueueAsyncDNSQuery(target, mp);
+               ok = requeueAsyncDNSQuery(target, mp);
                if (!ok) {
-                       SCLog(TRUE, LOG_ERR, CFSTR("processAsyncDNSReply enqueueAsyncDNSQuery() failed"));
+                       SCLog(TRUE, LOG_ERR, CFSTR("processAsyncDNSReply requeueAsyncDNSQuery() failed"));
                }
        }
 
@@ -3195,36 +3310,10 @@ check_resolver_reachability(ReachabilityStoreInfoRef    store_info,
        if (resolver_if_index) *resolver_if_index = 0;
 
        if (resolver->n_nameserver > 0) {
-#if    !TARGET_IPHONE_SIMULATOR
                *flags   = (SCNetworkReachabilityFlags)resolver->reach_flags;
                if (resolver_if_index != NULL) {
                        *resolver_if_index = resolver->if_index;
                }
-#else  // !TARGET_IPHONE_SIMULATOR
-               int     i;
-
-               *flags = kSCNetworkReachabilityFlagsReachable;
-
-               for (i = 0; i < resolver->n_nameserver; i++) {
-                       struct sockaddr         *address        = resolver->nameserver[i];
-                       ReachabilityInfo        ns_info;
-
-                       ok = checkAddress(store_info, address, resolver->if_index, &ns_info, log_prefix);
-                       if (!ok) {
-                               /* not today */
-                               break;
-                       }
-
-                       if ((i == 0) ||
-                           (rankReachability(ns_info.flags) < rankReachability(*flags))) {
-                               /* return the worst case result */
-                               *flags = ns_info.flags;
-                               if (resolver_if_index != NULL) {
-                                       *resolver_if_index = ns_info.if_index;
-                               }
-                       }
-               }
-#endif // !TARGET_IPHONE_SIMULATOR
                *haveDNS = TRUE;
        } else {
                *flags   = kSCNetworkReachabilityFlagsReachable;
@@ -3489,7 +3578,6 @@ _SC_R_checkResolverReachability(ReachabilityStoreInfoRef  store_info,
                                SCNetworkReachabilityFlags      *flags,
                                Boolean                         *haveDNS,
                                const char                      *nodename,
-                               const char                      *servname,
                                unsigned int                    if_index,
                                uint32_t                        *resolver_if_index,
                                int                             *dns_config_index,
@@ -3523,10 +3611,8 @@ _SC_R_checkResolverReachability(ReachabilityStoreInfoRef store_info,
 
        len = (nodename != NULL) ? strlen(nodename) : 0;
        if (len == 0) {
-               if ((servname == NULL) || (strlen(servname) == 0)) {
-                       // if no nodename or servname, return not reachable
-                       *flags = 0;
-               }
+               // if no nodename, return not reachable
+               *flags = 0;
                return ok;
        }
 
@@ -3537,7 +3623,8 @@ _SC_R_checkResolverReachability(ReachabilityStoreInfoRef  store_info,
                goto done;
        }
 
-       if (dns->config->n_resolver == 0) {
+       default_resolver = get_default_resolver(dns->config, if_index);
+       if (default_resolver == NULL) {
                // if no resolver configuration
                SCLog(_sc_debug, LOG_INFO, CFSTR("%sDNS: no resolvers"), log_prefix);
                goto done;
@@ -3555,8 +3642,6 @@ _SC_R_checkResolverReachability(ReachabilityStoreInfoRef  store_info,
                }
        }
 
-       default_resolver = get_default_resolver(dns->config, if_index);
-
        /*
         * check if the provided name matches a supplemental domain
         */
@@ -3599,7 +3684,8 @@ _SC_R_checkResolverReachability(ReachabilityStoreInfoRef  store_info,
                        if (*cp == '.') dots++;
                }
 
-               if (dots > ndots) {
+               /* Per KB: HT4845 */
+               if (dots >= ndots) {
                        useDefault = TRUE;
                }
        }
@@ -3701,37 +3787,11 @@ _SC_R_checkResolverReachability(ReachabilityStoreInfoRef        store_info,
 }
 
 
-Boolean
-_SC_checkResolverReachability(SCDynamicStoreRef                        *storeP,
-                             SCNetworkReachabilityFlags        *flags,
-                             Boolean                           *haveDNS,
-                             const char                        *nodename,
-                             const char                        *servname)
-{
-       Boolean                 ok;
-       ReachabilityStoreInfo   store_info;
-
-       ReachabilityStoreInfo_init(&store_info);
-       ok = ReachabilityStoreInfo_update(&store_info, storeP, AF_UNSPEC);
-       if (!ok) {
-               goto done;
-       }
-
-       ok = _SC_R_checkResolverReachability(&store_info, flags, haveDNS, nodename,
-                                            servname, 0, NULL, NULL, "");
-
-    done :
-
-       ReachabilityStoreInfo_free(&store_info);
-       return ok;
-}
-
 Boolean
 __SC_checkResolverReachabilityInternal(SCDynamicStoreRef               *storeP,
                                       SCNetworkReachabilityFlags       *flags,
                                       Boolean                          *haveDNS,
                                       const char                       *nodename,
-                                      const char                       *servname,
                                       uint32_t                         *resolver_if_index,
                                       int                              *dns_config_index)
 {
@@ -3745,9 +3805,9 @@ __SC_checkResolverReachabilityInternal(SCDynamicStoreRef          *storeP,
        }
 
        ok = _SC_R_checkResolverReachability(&store_info, flags, haveDNS, nodename,
-                                            servname, 0, resolver_if_index, dns_config_index, "");
+                                            0, resolver_if_index, dns_config_index, "");
 
-    done :
+       done :
 
        ReachabilityStoreInfo_free(&store_info);
        return ok;
@@ -3843,7 +3903,7 @@ _SC_checkResolverReachabilityByAddress(SCDynamicStoreRef          *storeP,
                        goto done;
        }
 
-       ok = _SC_R_checkResolverReachability(&store_info, flags, haveDNS, ptr_name, NULL, 0, NULL, NULL, "");
+       ok = _SC_R_checkResolverReachability(&store_info, flags, haveDNS, ptr_name, 0, NULL, NULL, "");
 
     done :
 
@@ -3852,153 +3912,198 @@ _SC_checkResolverReachabilityByAddress(SCDynamicStoreRef              *storeP,
 }
 
 
-static Boolean
-startAsyncDNSQuery(SCNetworkReachabilityRef target)
-{
-       int                             error   = 0;
-       mach_port_t                     mp      = MACH_PORT_NULL;
-       Boolean                         ok;
-       SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
+#pragma mark -
+#pragma mark DNSServiceGetAddrInfo support
 
-       __dns_query_start(&targetPrivate->dnsQueryStart, &targetPrivate->dnsQueryEnd);
 
-#ifdef HAVE_GETADDRINFO_INTERFACE_ASYNC_CALL
-       if (targetPrivate->if_index == 0) {
-#endif /* HAVE_GETADDRINFO_INTERFACE_ASYNC_CALL */
-               error = getaddrinfo_async_start(&mp,
-                                               targetPrivate->name,
-                                               targetPrivate->serv,
-                                               &targetPrivate->hints,
-                                               __SCNetworkReachabilityCallbackSetResolvedAddress,
-                                               (void *)target);
-#ifdef HAVE_GETADDRINFO_INTERFACE_ASYNC_CALL
-       } else {
-               mp = _getaddrinfo_interface_async_call(targetPrivate->name,
-                                                      targetPrivate->serv,
-                                                      &targetPrivate->hints,
-                                                      targetPrivate->if_name,
-                                                      __SCNetworkReachabilityCallbackSetResolvedAddress,
-                                                      (void *)target);
-               if (mp == MACH_PORT_NULL) {
-                       error = EAI_SYSTEM;
-               }
-       }
-#endif /* HAVE_GETADDRINFO_INTERFACE_ASYNC_CALL */
-       if (error != 0) {
-               /* save the error associated with the attempt to resolve the name */
-               __SCNetworkReachabilityCallbackSetResolvedAddress(error, NULL, (void *)target);
-               return FALSE;
-       }
+#ifdef USE_DNSSERVICEGETADDRINFO
 
-       ok = enqueueAsyncDNSQuery(target, mp);
-       return ok;
-}
+/*
+ * DNS query handling
+ *
+ * Notes :
+ *
+ * 1. We have a "contract" with mDNSResponder that for EVERY network
+ *    or DNS configuration change that should warrant our [re-]starting
+ *    a query, mDNSResponder will acknowledge the latest DNS configuration.
+ *
+ * 2. IPMonitor also posts a notification AFTER every network or DNS
+ *    configuration change.
+ *
+ * 3. We use IPMonitor's "trailing edge" as a signal to restart any
+ *    by-name queries.
+ */
 
 
-#pragma mark -
+// Note: protected by _hn_changes_queue()
+static SCDynamicStoreCallBack  dns_callback            = NULL;
+static int                     dns_refresh_token;
+static Boolean                 dns_refresh_token_valid = FALSE;
+static SCDynamicStoreRef       dns_store               = NULL;
 
 
-static Boolean
-enqueueAsyncDNSRetry(SCNetworkReachabilityRef  target)
+/*
+ * dns_refresh_handler
+ *
+ * Called to notify/update all SCNetworkReachability by-name targets of
+ * a network/DNS change.  The change should [re-]start a DNS query to
+ * resolve the name.
+ * - caller must be running on the _hn_changes_queue()
+ */
+static void
+dns_refresh_handler()
 {
-       int64_t                         delay;
-       dispatch_source_t               source;
-       SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
-
-       MUTEX_ASSERT_HELD(&targetPrivate->lock);
+       CFArrayRef      changes;
+       CFStringRef     key;
 
-       source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,
-                                       0,
-                                       0,
-                                       __SCNetworkReachability_concurrent_queue());
-       if (source == NULL) {
-               SCLog(TRUE, LOG_ERR, CFSTR("SCNetworkReachability retry dispatch_source_create() failed"));
-               return FALSE;
+       if (!dns_refresh_token_valid || (dns_callback == NULL)) {
+               return;
        }
 
-       // retain the target ... and release it when the [timer] source is released
-       CFRetain(target);
-       dispatch_set_context(source, (void *)target);
-       dispatch_set_finalizer_f(source, (dispatch_function_t)CFRelease);
+       key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+                                                        kSCDynamicStoreDomainState,
+                                                        kSCEntNetDNS);
+       changes = CFArrayCreate(NULL, (const void **)&key, 1, &kCFTypeArrayCallBacks);
+       (*dns_callback)(dns_store, changes, NULL);
+       CFRelease(changes);
+       CFRelease(key);
 
-       dispatch_source_set_event_handler(source, ^(void) {
-               __SCNetworkReachabilityPerformInlineNoLock(target, TRUE);
-       });
+       return;
+}
 
-       // start a one-shot timer
-       delay = targetPrivate->dnsRetryCount * EAI_NONAME_RETRY_DELAY_USEC * NSEC_PER_USEC;
-       dispatch_source_set_timer(source,
-                                 dispatch_time(DISPATCH_TIME_NOW, delay),      // start
-                                 0,                                            // interval
-                                 10 * NSEC_PER_MSEC);                          // leeway
 
-       targetPrivate->dnsRetry = source;
-       dispatch_resume(source);
+/*
+ * dns_refresh_enable
+ *
+ * Called to monitor for network/DNS changes that should restart a DNS query.
+ * - caller must be running on the _hn_changes_queue()
+ */
+static Boolean
+dns_refresh_enable(dispatch_queue_t q, SCDynamicStoreRef store, SCDynamicStoreCallBack callback)
+{
+       uint32_t        status;
+
+       dns_callback = callback;
+       dns_store = CFRetain(store);
+
+       status = notify_register_dispatch(_SC_NOTIFY_NETWORK_CHANGE,
+                                         &dns_refresh_token,
+                                         q,
+                                         ^(int token){
+                                                 dns_refresh_handler();
+                                         });
+       if (status != NOTIFY_STATUS_OK) {
+               SCLog(TRUE, LOG_INFO, CFSTR("notify_register_dispatch() failed, status=%lu"), status);
+               return FALSE;
+       }
+
+       dns_refresh_token_valid = TRUE;
 
        return TRUE;
 }
 
 
+/*
+ * dns_refresh_disable
+ *
+ * Called to stop monitoring for network/DNS changes
+ * - caller must be running on the _hn_changes_queue()
+ */
 static void
-dequeueAsyncDNSRetry(SCNetworkReachabilityRef  target)
+dns_refresh_disable()
 {
-       SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
-
-       MUTEX_ASSERT_HELD(&targetPrivate->lock);
-
-       if (targetPrivate->dnsRetry != NULL) {
-               dispatch_source_cancel(targetPrivate->dnsRetry);
-               dispatch_release(targetPrivate->dnsRetry);
-               targetPrivate->dnsRetry = NULL;
-       }
-
+       (void)notify_cancel(dns_refresh_token);
+       dns_refresh_token_valid = FALSE;
+       CFRelease(dns_store);
+       dns_store = NULL;
+       dns_callback = NULL;
        return;
 }
 
+#endif // USE_DNSSERVICEGETADDRINFO
+
 
 #pragma mark -
+#pragma mark [m]DNS Queries
+
+
+static void
+dequeueDNSQuery(SCNetworkReachabilityRef target);
 
 
 static dispatch_queue_t
-_llq_queue()
+_dns_queue()
 {
        static dispatch_once_t  once;
        static dispatch_queue_t q;
 
        dispatch_once(&once, ^{
-               q = dispatch_queue_create("SCNetworkReachabilty.longLivedQueries", NULL);
+               q = dispatch_queue_create("SCNetworkReachabilty.DNSService", NULL);
        });
 
        return q;
 }
 
 
+#ifdef USE_DNSSERVICEGETADDRINFO
+
+/*
+ * _dns_complete
+ */
+static __inline__ Boolean
+_dns_complete(SCNetworkReachabilityRef target)
+{
+       SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
+
+       if ((targetPrivate->dnsHaveV4 && targetPrivate->dnsHaveV6) ||
+           targetPrivate->dnsHaveError ||
+           targetPrivate->dnsHaveTimeout) {
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+
 /*
- * _llq_notify
+ * _dns_notify
  *
  * Called to push out a target's DNS changes
- * - caller must be running on the _llq_queue()
+ * - caller must be running on the _dns_queue()
  */
 static void
-_llq_notify(const void *value, void *context)
+_dns_notify(const void *value, void *context)
 {
        SCNetworkReachabilityRef        target          = (SCNetworkReachabilityRef)value;
        SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
 
        MUTEX_LOCK(&targetPrivate->lock);
 
-       __dns_query_end(target,
-                       (targetPrivate->resolvedAddressError == NETDB_SUCCESS), // if successful query
-                       dns_query_llq,                                          // long-lived-query
-                       &targetPrivate->dnsQueryStart,                          // start time
-                       &targetPrivate->dnsQueryEnd);                           // end time
+       if (_dns_complete(target)) {
+               __mark_operation_end(target,
+                                    (targetPrivate->resolvedError == NETDB_SUCCESS),   // if successful query
+                                    dns_query_mdns,                                    // [m]DNS query
+                                    &targetPrivate->dnsQueryStart,                     // start time
+                                    &targetPrivate->dnsQueryEnd);                      // end time
 
-       if (targetPrivate->scheduled) {
-               __SCNetworkReachabilityPerform(target);
-       }
+               // update target info
+               if (targetPrivate->resolvedAddresses != NULL) {
+                       CFRelease(targetPrivate->resolvedAddresses);
+               }
+               targetPrivate->resolvedAddresses = targetPrivate->dnsAddresses;
+               targetPrivate->dnsAddresses      = NULL;
 
-       // last long-lived-query end time is new start time
-       targetPrivate->dnsQueryStart = targetPrivate->dnsQueryEnd;
+               targetPrivate->resolvedError     = targetPrivate->dnsError;
+               targetPrivate->dnsError          = NETDB_SUCCESS;
+
+               dequeueDNSQuery(target);
+
+               targetPrivate->needResolve = FALSE;
+
+               if (targetPrivate->scheduled) {
+                       __SCNetworkReachabilityPerformLocked(target);
+               }
+       }
 
        MUTEX_UNLOCK(&targetPrivate->lock);
        return;
@@ -4006,13 +4111,44 @@ _llq_notify(const void *value, void *context)
 
 
 /*
- * _llq_callback
+ * _dns_mark
+ */
+static __inline__ void
+_dns_mark(SCNetworkReachabilityRef target, Boolean valid, const struct sockaddr *sa)
+{
+       SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
+
+       if (!valid) {
+               targetPrivate->dnsHaveError = TRUE;
+               return;
+       }
+
+       if (sa == NULL) {
+               targetPrivate->dnsHaveTimeout = TRUE;
+               return;
+       }
+
+       switch (sa->sa_family) {
+               case AF_INET :
+                       targetPrivate->dnsHaveV4 = TRUE;
+                       break;
+               case AF_INET6 :
+                       targetPrivate->dnsHaveV6 = TRUE;
+                       break;
+       }
+
+       return;
+}
+
+
+/*
+ * _dns_callback
  *
- * Called to process mDNSResponder long-lived-query updates
- * - caller must be running on the _llq_queue()
+ * Called to process [m]DNS query updates
+ * - caller must be running on the _dns_queue()
  */
 static void
-_llq_callback(DNSServiceRef            sdRef,
+_dns_callback(DNSServiceRef            sdRef,
              DNSServiceFlags           flags,
              uint32_t                  interfaceIndex,
              DNSServiceErrorType       errorCode,
@@ -4026,81 +4162,105 @@ _llq_callback(DNSServiceRef            sdRef,
 
        MUTEX_LOCK(&targetPrivate->lock);
 
-       if (targetPrivate->llqTimer != NULL) {
-               dispatch_source_cancel(targetPrivate->llqTimer);
-               dispatch_release(targetPrivate->llqTimer);
-               targetPrivate->llqTimer = NULL;
+       if (sdRef != targetPrivate->dnsTarget) {
+               // if this DNSServiceRef is no longer associated with
+               // this target
+               MUTEX_UNLOCK(&targetPrivate->lock);
+               return;
        }
 
        switch (errorCode) {
                case kDNSServiceErr_NoError :
                        if (address != NULL) {
                                CFMutableArrayRef       addresses;
-                               CFDataRef               llqAddress;
+                               CFDataRef               dnsAddress;
+                               CFIndex                 i;
+
+                               _dns_mark(target, TRUE, address);
 
-                               if (targetPrivate->resolvedAddress != NULL) {
-                                       if (isA_CFArray(targetPrivate->resolvedAddress)) {
-                                               addresses = CFArrayCreateMutableCopy(NULL, 0, targetPrivate->resolvedAddress);
+                               if (targetPrivate->dnsAddresses != NULL) {
+                                       if (isA_CFArray(targetPrivate->dnsAddresses)) {
+                                               addresses = CFArrayCreateMutableCopy(NULL, 0, targetPrivate->dnsAddresses);
                                        } else {
                                                addresses = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
                                        }
 
-                                       CFRelease(targetPrivate->resolvedAddress);
-                                       targetPrivate->resolvedAddress = NULL;
+                                       CFRelease(targetPrivate->dnsAddresses);
+                                       targetPrivate->dnsAddresses = NULL;
                                } else {
                                        addresses = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
                                }
 
-                               llqAddress = CFDataCreate(NULL, (void *)address, address->sa_len);
+                               dnsAddress = CFDataCreate(NULL, (void *)address, address->sa_len);
+                               i = CFArrayGetFirstIndexOfValue(addresses,
+                                                               CFRangeMake(0, CFArrayGetCount(addresses)),
+                                                               dnsAddress);
                                if (flags & kDNSServiceFlagsAdd) {
                                        // add address
-                                       CFArrayAppendValue(addresses, llqAddress);
+                                       if (i == kCFNotFound) {
+                                               CFArrayAppendValue(addresses, dnsAddress);
+                                       }
+#ifdef HANDLE_RMV_REQUESTS
                                } else {
-                                       CFIndex i;
-
                                        // remove address
-                                       i = CFArrayGetFirstIndexOfValue(addresses,
-                                                                       CFRangeMake(0, CFArrayGetCount(addresses)),
-                                                                       llqAddress);
                                        if (i != kCFNotFound) {
                                                CFArrayRemoveValueAtIndex(addresses, i);
                                        }
+#endif // HANDLE_RMV_REQUESTS
                                }
-                               CFRelease(llqAddress);
+                               CFRelease(dnsAddress);
 
                                if (CFArrayGetCount(addresses) > 0) {
-                                       targetPrivate->resolvedAddress      = addresses;
-                                       targetPrivate->resolvedAddressError = NETDB_SUCCESS;
+                                       targetPrivate->dnsAddresses = addresses;
+                                       targetPrivate->dnsError     = NETDB_SUCCESS;
                                } else {
                                        // if host not found
-                                       targetPrivate->resolvedAddress      = CFRetain(kCFNull);
-                                       targetPrivate->resolvedAddressError = EAI_NONAME;
+                                       targetPrivate->dnsAddresses = CFRetain(kCFNull);
+                                       targetPrivate->dnsError     = EAI_NONAME;
                                        CFRelease(addresses);
                                }
 
-                               targetPrivate->needResolve = FALSE;
                        }
                        break;
-               case kDNSServiceErr_NoSuchRecord :
+               case kDNSServiceErr_BadParam :
+                       _dns_mark(target, FALSE, NULL);
+
+                       if (targetPrivate->dnsAddresses != NULL) {
+                               CFRelease(targetPrivate->dnsAddresses);
+                       }
+                       targetPrivate->dnsAddresses = CFRetain(kCFNull);
+                       targetPrivate->dnsError     = EAI_NONAME;
+                       break;
+               case kDNSServiceErr_NoSuchRecord :
                        if (address != NULL) {
                                // no IPv4/IPv6 address for name (NXDOMAIN)
-                               if (targetPrivate->resolvedAddress == NULL) {
-                                       targetPrivate->resolvedAddress      = CFRetain(kCFNull);
-                                       targetPrivate->resolvedAddressError = EAI_NONAME;
+
+                               _dns_mark(target, TRUE, address);
+
+                               if (targetPrivate->dnsAddresses == NULL) {
+                                       targetPrivate->dnsAddresses = CFRetain(kCFNull);
+                                       targetPrivate->dnsError     = EAI_NONAME;
                                }
-                               targetPrivate->needResolve = FALSE;
                        }
                        break;
                case kDNSServiceErr_Timeout :
-                       if (targetPrivate->resolvedAddress == NULL) {
-                               targetPrivate->resolvedAddress      = CFRetain(kCFNull);
-                               targetPrivate->resolvedAddressError = EAI_NONAME;
+                       _dns_mark(target, TRUE, NULL);
+
+                       if (targetPrivate->dnsAddresses == NULL) {
+                               targetPrivate->dnsAddresses = CFRetain(kCFNull);
+                               targetPrivate->dnsError     = EAI_NONAME;
                        }
-                       targetPrivate->needResolve = FALSE;
                        break;
+               case kDNSServiceErr_ServiceNotRunning :
+                       // mDNSResponder crashed, restart query
+                       DNSServiceRefDeallocate(dnsMain);
+                       dnsMain = NULL;
+                       dnsCount = 0;
                default :
+                       _dns_mark(target, FALSE, NULL);
+
                        SCLog(TRUE, LOG_ERR,
-                             CFSTR("%sSCNetworkReachability _llq_callback w/error=%d"),
+                             CFSTR("%sSCNetworkReachability _dns_callback w/error=%d"),
                              targetPrivate->log_prefix,
                              errorCode);
                        break;
@@ -4108,20 +4268,34 @@ _llq_callback(DNSServiceRef             sdRef,
 
        MUTEX_UNLOCK(&targetPrivate->lock);
 
+       if (errorCode == kDNSServiceErr_ServiceNotRunning) {
+               dispatch_async(_hn_changes_queue(), ^{
+                       dns_refresh_handler();
+               });
+
+               // and flush the dnsUpdated queue as any DNS results we may have
+               // accumulated are no longer valid.
+               if (dnsUpdated != NULL) {
+                       CFRelease(dnsUpdated);
+                       dnsUpdated = NULL;
+               }
+               return;
+       }
+
        // the "more coming" flag applies to DNSService callouts for any/all
        // hosts that are being watched so we need to keep track of the targets
        // we have updated.  When we [finally] have the last callout then we
        // push our notifications for all of the updated targets.
 
-       if (llqUpdated == NULL) {
-               llqUpdated = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
+       if (dnsUpdated == NULL) {
+               dnsUpdated = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
        }
-       CFSetAddValue(llqUpdated, target);
+       CFSetAddValue(dnsUpdated, target);
 
        if (!(flags & kDNSServiceFlagsMoreComing)) {
-               CFSetApplyFunction(llqUpdated, _llq_notify, NULL);
-               CFRelease(llqUpdated);
-               llqUpdated = NULL;
+               CFSetApplyFunction(dnsUpdated, _dns_notify, NULL);
+               CFRelease(dnsUpdated);
+               dnsUpdated = NULL;
        }
 
        return;
@@ -4129,191 +4303,271 @@ _llq_callback(DNSServiceRef           sdRef,
 
 
 static Boolean
-enqueueLongLivedQuery(SCNetworkReachabilityRef target)
+enqueueDNSQuery(SCNetworkReachabilityRef target)
 {
        SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
 
        MUTEX_ASSERT_HELD(&targetPrivate->lock);
 
-       if (targetPrivate->serv != NULL) {
-               // if "serv" provided, can't use DNSServiceGetAddrInfo
-               return FALSE;
-       }
-
-       if (memcmp(&targetPrivate->hints, &HINTS_DEFAULT, sizeof(targetPrivate->hints)) != 0) {
-               // non-default "hints" provided, can't use DNSServiceGetAddrInfo
-               return FALSE;
-       }
-
-       // mark the long lived query active
-       targetPrivate->llqActive = TRUE;
+       // clear DNS flags, mark the [m]DNS query active
+       targetPrivate->dnsFlags = 0;
+       targetPrivate->dnsActive = TRUE;
 
        // track the DNS resolution time
-       __dns_query_start(&targetPrivate->dnsQueryStart, &targetPrivate->dnsQueryEnd);
+       __mark_operation_start(&targetPrivate->dnsQueryStart, &targetPrivate->dnsQueryEnd);
 
        CFRetain(target);
-       dispatch_async(_llq_queue(), ^{
-               DNSServiceErrorType     err;
-               dispatch_source_t       source;
+       dispatch_async(_dns_queue(), ^{
+               DNSServiceErrorType     err     = kDNSServiceErr_NoError;
+               DNSServiceRef           sdRef   = NULL;
 
-               MUTEX_LOCK(&targetPrivate->lock);
-
-               if (targetPrivate->llqTarget != NULL) {
+               if (targetPrivate->dnsTarget != NULL) {
                        // if already running
-                       MUTEX_UNLOCK(&targetPrivate->lock);
                        CFRelease(target);
                        return;
                }
 
                // if needed, start interacting with mDNSResponder
+               // Note: we must not hold a [target] lock while interacting
 
-               if (llqMain == NULL) {
-                       err = DNSServiceCreateConnection(&llqMain);
+               if (dnsMain == NULL) {
+                       err = DNSServiceCreateConnection(&dnsMain);
                        if (err != kDNSServiceErr_NoError) {
                                SCLog(TRUE, LOG_ERR,
-                                     CFSTR("DNSServiceCreateConnection(&llqMain) failed, error = %d"),
+                                     CFSTR("DNSServiceCreateConnection(&dnsMain) failed, error = %d"),
                                      err);
-
-                               targetPrivate->llqActive = FALSE;
-
-                               MUTEX_UNLOCK(&targetPrivate->lock);
-                               CFRelease(target);
-                               return;
+                               goto done;
                        }
 
-                       err = DNSServiceSetDispatchQueue(llqMain, _llq_queue());
+                       err = DNSServiceSetDispatchQueue(dnsMain, _dns_queue());
                        if (err != kDNSServiceErr_NoError) {
                                SCLog(TRUE, LOG_ERR,
                                      CFSTR("DNSServiceSetDispatchQueue() failed, error = %d"),
                                      err);
-                               DNSServiceRefDeallocate(llqMain);
-                               llqMain = NULL;
-
-                               targetPrivate->llqActive = FALSE;
-
-                               MUTEX_UNLOCK(&targetPrivate->lock);
-                               CFRelease(target);
-                               return;
+                               DNSServiceRefDeallocate(dnsMain);
+                               dnsMain = NULL;
+                               goto done;
                        }
                }
 
-               // start a long-lived-query for this target
+               // start an [m]DNS query for this target
 
-               targetPrivate->llqTarget = llqMain;
-               err = DNSServiceGetAddrInfo(&targetPrivate->llqTarget,          // sdRef
+               sdRef = dnsMain;
+               err = DNSServiceGetAddrInfo(&sdRef,                             // sdRef
                                            kDNSServiceFlagsReturnIntermediates // flags
-                                           | kDNSServiceFlagsShareConnection,
+                                           | kDNSServiceFlagsShareConnection
+                                           | kDNSServiceFlagsTimeout,
                                            targetPrivate->if_index,            // interfaceIndex
                                            0,                                  // protocol
                                            targetPrivate->name,                // hostname
-                                           _llq_callback,                      // callback
+                                           _dns_callback,                      // callback
                                            (void *)target);                    // context
-               if (err != kDNSServiceErr_NoError) {
-                       SCLog(TRUE, LOG_ERR,
-                             CFSTR("DNSServiceGetAddrInfo() failed, error = %d"),
-                             err);
-                       targetPrivate->llqTarget = NULL;
-                       if (llqCount == 0) {
-                               // if this was the first request
-                               DNSServiceRefDeallocate(llqMain);
-                               llqMain = NULL;
+               if (err == kDNSServiceErr_NoError) {
+                       dnsCount++;
+               } else {
+                       sdRef = NULL;
+                       if ((dnsCount == 0) || (err == kDNSServiceErr_ServiceNotRunning)) {
+                               // if this was the first request or the service is dead
+                               DNSServiceRefDeallocate(dnsMain);
+                               dnsMain = NULL;
+                               dnsCount = 0;
                        }
-
-                       targetPrivate->llqActive = FALSE;
-
-                       MUTEX_UNLOCK(&targetPrivate->lock);
-                       CFRelease(target);
-                       return;
                }
 
-               llqCount++;
-
-               // if case we don't get any callbacks from our long-lived-query (this
-               // could happen if the DNS servers do not respond), we start a timer
-               // to ensure that we fire off at least one reachability callback.
-
-               source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,
-                                               0,
-                                               0,
-                                               _llq_queue());
-               if (source != NULL) {
-                       // retain the target ... and release it when the [timer] source is released
-                       CFRetain(target);
-                       dispatch_set_context(source, (void *)target);
-                       dispatch_set_finalizer_f(source, (dispatch_function_t)CFRelease);
-
-                       dispatch_source_set_event_handler(source, ^(void) {
-                               _llq_callback(NULL,                     // sdRef
-                                             0,                        // flags
-                                             0,                        // interfaceIndex
-                                             kDNSServiceErr_Timeout,   // errorCode
-                                             NULL,                     // hostname
-                                             NULL,                     // address
-                                             0,                        // ttl
-                                             (void *)target);          // context
-                       });
+               switch (err) {
+                       case kDNSServiceErr_NoError :
+                               break;
+                       case kDNSServiceErr_BadParam :
+                               CFRetain(target);
+                               dispatch_async(_dns_queue(), ^{
+                                       _dns_callback(NULL,                     // sdRef
+                                                     0,                        // flags
+                                                     0,                        // interfaceIndex
+                                                     kDNSServiceErr_BadParam,  // errorCode
+                                                     NULL,                     // hostname
+                                                     NULL,                     // address
+                                                     0,                        // ttl
+                                                     (void *)target);          // context
+                                       CFRelease(target);
+                               });
+                               break;
+                       default :
+                               SCLog(TRUE, LOG_ERR,
+                                     CFSTR("DNSServiceGetAddrInfo() failed, error = %d"),
+                                     err);
+                               break;
+               }
 
-                       dispatch_source_set_timer(source,
-                                                 dispatch_time(DISPATCH_TIME_NOW,
-                                                               LLQ_TIMEOUT_NSEC),      // start
-                                                 0,                                    // interval
-                                                 10 * NSEC_PER_MSEC);                  // leeway
+           done :
 
-                       targetPrivate->llqTimer = source;
-                       dispatch_resume(source);
+               MUTEX_LOCK(&targetPrivate->lock);
+               if (err == kDNSServiceErr_NoError) {
+                       // query active, save DNSServiceRef, retain target reference
+                       targetPrivate->dnsMain = dnsMain;
+                       targetPrivate->dnsTarget = sdRef;
+                       MUTEX_UNLOCK(&targetPrivate->lock);
                } else {
-                       SCLog(TRUE, LOG_ERR,
-                             CFSTR("SCNetworkReachability llq dispatch_source_create(no-reply) failed"));
+                       // query no longer active, release target reference
+                       targetPrivate->dnsActive = FALSE;
+                       MUTEX_UNLOCK(&targetPrivate->lock);
+                       CFRelease(target);
+                       if (err == kDNSServiceErr_ServiceNotRunning) {
+                               dispatch_async(_hn_changes_queue(), ^{
+                                       dns_refresh_handler();
+                               });
+                       }
                }
 
-               MUTEX_UNLOCK(&targetPrivate->lock);
                return;
        });
 
        return TRUE;
 }
 
+#endif // USE_DNSSERVICEGETADDRINFO
+
 
 static void
-dequeueLongLivedQuery(SCNetworkReachabilityRef target)
+dequeueDNSQuery(SCNetworkReachabilityRef target)
 {
        DNSServiceRef                   sdRef;
        SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
 
        MUTEX_ASSERT_HELD(&targetPrivate->lock);
 
-       // terminate the [target] llq timer
-       if (targetPrivate->llqTimer != NULL) {
-               dispatch_source_cancel(targetPrivate->llqTimer);
-               dispatch_release(targetPrivate->llqTimer);
-               targetPrivate->llqTimer = NULL;
-       }
-
-       // terminate the [target] long lived query
-       sdRef = targetPrivate->llqTarget;
-       targetPrivate->llqTarget = NULL;
+       // terminate the [target] [m]DNS query
+       sdRef = targetPrivate->dnsTarget;
+       targetPrivate->dnsTarget = NULL;
 
-       // mark the long lived query NOT active
-       targetPrivate->llqActive = FALSE;
+       // mark the [m]DNS query NOT active
+       targetPrivate->dnsActive = FALSE;
 
-       if (sdRef != NULL) {
-               dispatch_async(_llq_queue(), ^{
+       // don't do anything if the sdRef is not valid (e.g., "dnsMain" changed)
+       if (sdRef != NULL
+           && targetPrivate->dnsMain == dnsMain) {
+               dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 3LL * NSEC_PER_SEC),
+                              _dns_queue(),
+                              ^{
                        DNSServiceRefDeallocate(sdRef);
                        CFRelease(target);
 
-                       llqCount--;
-                       if (llqCount == 0) {
+                       dnsCount--;
+                       if (dnsCount == 0) {
                                // if no more queries active
-                               DNSServiceRefDeallocate(llqMain);
-                               llqMain = NULL;
+                               DNSServiceRefDeallocate(dnsMain);
+                               dnsMain = NULL;
                        }
                });
        }
 
+       if (targetPrivate->dnsAddresses != NULL) {
+               CFRelease(targetPrivate->dnsAddresses);
+               targetPrivate->dnsAddresses = NULL;
+       }
+       targetPrivate->dnsError = NETDB_SUCCESS;
+
+       return;
+}
+
+
+#pragma mark -
+#pragma mark Network Information support
+
+
+// Note: protected by _hn_changes_queue()
+static SCDynamicStoreCallBack  network_changed_callback        = NULL;
+static int                     network_changed_token;
+static Boolean                 network_changed_token_valid     = FALSE;
+static SCDynamicStoreRef       network_change_store            = NULL;
+
+
+/*
+ * nwi_refresh_handler
+ *
+ * Called to notify/update network changed events
+ * - caller must be running on the _hn_changes_queue()
+ */
+static void
+nwi_refresh_handler()
+{
+       CFArrayRef      changes;
+       CFStringRef     key;
+
+       if (!network_changed_token_valid || (network_changed_callback == NULL)) {
+               return;
+       }
+
+       // Fake a network change.
+       key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+                                                        kSCDynamicStoreDomainState,
+                                                        kSCEntNetIPv4);
+
+       changes = CFArrayCreate(NULL, (const void **)&key, 1, &kCFTypeArrayCallBacks);
+       (*network_changed_callback)(network_change_store, changes, NULL);
+       CFRelease(changes);
+       CFRelease(key);
+
        return;
 }
 
 
+/*
+ * nwi_refresh_enable
+ *
+ * Called to monitor for network changes.
+ * - caller must be running on the _hn_changes_queue()
+ */
+static Boolean
+nwi_refresh_enable(dispatch_queue_t q, SCDynamicStoreRef store, SCDynamicStoreCallBack callback)
+{
+       uint32_t        status;
+
+       network_changed_callback = callback;
+       network_change_store = CFRetain(store);
+
+       status = notify_register_dispatch(_SC_NOTIFY_NETWORK_CHANGE_NWI,        // trailing nwi_state_get_notify_key()
+                                         &network_changed_token,
+                                         q,
+                                         ^(int token){
+                                                 nwi_refresh_handler();
+                                         });
+       if (status != NOTIFY_STATUS_OK) {
+               SCLog(TRUE, LOG_INFO, CFSTR("notify_register_dispatch() failed for network changes, status=%lu"), status);
+               return FALSE;
+       }
+
+       network_changed_token_valid = TRUE;
+
+       return TRUE;
+}
+
+
+/*
+ * nwi_refresh_disable
+ *
+ * Called to stop monitoring for network changes
+ * - caller must be running on the _hn_changes_queue()
+ */
+static void
+nwi_refresh_disable()
+{
+       if (network_changed_token_valid) {
+               (void)notify_cancel(network_changed_token);
+               network_changed_token_valid = FALSE;
+       }
+       if (network_change_store != NULL) {
+               CFRelease(network_change_store);
+               network_change_store = NULL;
+               network_changed_callback = NULL;
+       }
+       return;
+}
+
+
+
+
+
+
 #pragma mark -
 #pragma mark OnDemand
 
@@ -4363,9 +4617,16 @@ __SCNetworkReachabilityOnDemandCheckCallback(SCNetworkReachabilityRef    onDemandSe
                return;
        }
 
-       SCLog(_sc_debug, LOG_INFO, CFSTR("%sOnDemand \"server\" status changed"),
-             targetPrivate->log_prefix);
-       __SCNetworkReachabilityPerform(target);
+       SCLog(_sc_debug, LOG_INFO, CFSTR("%sOnDemand \"server\" status changed (now 0x%08x)"),
+             targetPrivate->log_prefix,
+             onDemandFlags);
+
+       if (targetPrivate->type == reachabilityTypeName) {
+               // make sure that we resolve the name again
+               targetPrivate->needResolve = TRUE;
+       }
+
+       __SCNetworkReachabilityPerformLocked(target);
 
        MUTEX_UNLOCK(&targetPrivate->lock);
 
@@ -4379,21 +4640,20 @@ __SCNetworkReachabilityOnDemandCheck(ReachabilityStoreInfoRef   store_info,
                                     Boolean                    onDemandRetry,
                                     SCNetworkReachabilityFlags *flags)
 {
-       Boolean                         ok;
-       Boolean                         onDemand                = FALSE;
+       SCNetworkConnectionRef          connection              = NULL;
+       SCNetworkConnectionType         connectionType          = kSCNetworkConnectionTypeUnknown;
+       Boolean                         isAppLayerVPN           = FALSE;
+       Boolean                         isOnDemandService       = FALSE;
+       Boolean                         ok                      = FALSE;
        CFStringRef                     onDemandRemoteAddress   = NULL;
        CFStringRef                     onDemandServiceID       = NULL;
-       SCNetworkConnectionStatus       onDemandStatus;
-       SCDynamicStoreRef               store;
+       SCNetworkConnectionStatus       onDemandStatus          = kSCNetworkConnectionInvalid;
+       CFMutableDictionaryRef          selectOptions           = NULL;
+       Boolean                         success                 = FALSE;
        SCNetworkReachabilityPrivateRef targetPrivate           = (SCNetworkReachabilityPrivateRef)target;
 
        MUTEX_ASSERT_HELD(&targetPrivate->lock);
 
-//     SCLog(_sc_debug, LOG_INFO,
-//           CFSTR("%s__SCNetworkReachabilityOnDemandCheck %s"),
-//           targetPrivate->log_prefix,
-//           onDemandRetry ? "after" : "before");
-
        if (targetPrivate->onDemandName == NULL) {
                targetPrivate->onDemandName = CFStringCreateWithCString(NULL, targetPrivate->name, kCFStringEncodingUTF8);
        }
@@ -4401,17 +4661,70 @@ __SCNetworkReachabilityOnDemandCheck(ReachabilityStoreInfoRef   store_info,
        /*
         * check if an OnDemand VPN configuration matches the name.
         */
-       store = store_info->store;
-       ok = __SCNetworkConnectionCopyOnDemandInfoWithName(&store,
-                                                          targetPrivate->onDemandName,
-                                                          onDemandRetry,
-                                                          &onDemandServiceID,
-                                                          &onDemandStatus,
-                                                          &onDemandRemoteAddress);
-       if ((store_info->store == NULL) && (store != NULL)) {
-               // if an SCDynamicStore session was added, keep it
-               store_info->store = store;
+
+       connection = SCNetworkConnectionCreate(kCFAllocatorDefault, NULL, NULL);
+       if (connection == NULL) {
+               goto done;
+       }
+
+       /* set select options */
+       selectOptions = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+       if (selectOptions == NULL) {
+               goto done;
+       }
+
+       CFDictionaryAddValue(selectOptions, kSCNetworkConnectionSelectionOptionOnDemandHostName, targetPrivate->onDemandName);
+       CFDictionaryAddValue(selectOptions, kSCNetworkConnectionSelectionOptionOnDemandRetry, onDemandRetry ? kCFBooleanTrue : kCFBooleanFalse);
+       CFDictionaryAddValue(selectOptions, kSCNetworkConnectionSelectionOptionNoUserPrefs, kCFBooleanTrue);
+
+       /* select service. May be On Demand or App Layer VPN */
+       if (!SCNetworkConnectionSelectServiceWithOptions(connection, selectOptions)) {
+               goto done;
+       }
+
+       /* get reachability flags (of VPN server) */
+       (void) SCNetworkConnectionGetReachabilityInfo(connection, flags, NULL);
+
+       connectionType = SCNetworkConnectionGetType(connection);
+       if (connectionType == kSCNetworkConnectionTypeAppLayerVPN) {
+               isAppLayerVPN = TRUE;
+       }
+
+       /* get on-demand info */
+       onDemandServiceID = SCNetworkConnectionCopyServiceID(connection);
+       if (SCNetworkConnectionCopyOnDemandInfo(connection, &onDemandRemoteAddress, &onDemandStatus)) {
+               isOnDemandService = TRUE;
+               ok = TRUE;
+       }
+
+       /* handle non-OnDemand App-Layer VPN */
+       if (isAppLayerVPN && !isOnDemandService) {
+               SCLog(_sc_debug, LOG_INFO, CFSTR("%s  status  * = 0x%08x (App-Layer VPN)"),
+                     targetPrivate->log_prefix,
+                     *flags);
+               if (*flags & kSCNetworkReachabilityFlagsReachable) {
+                       // if VPN "server" is reachable
+
+                       if (!(*flags & kSCNetworkReachabilityFlagsTransientConnection)) {
+                               // start w/clean flags if not already layered on a transient network
+                               *flags = kSCNetworkReachabilityFlagsReachable;
+                       }
+
+                       *flags |= kSCNetworkReachabilityFlagsTransientConnection;
+                       if (onDemandStatus != kSCNetworkConnectionConnected) {
+                               *flags |= kSCNetworkReachabilityFlagsConnectionRequired;
+                       }
+
+                       SCLog(_sc_debug, LOG_INFO, CFSTR("%s  status    = isReachable%s"),
+                             (onDemandStatus != kSCNetworkConnectionConnected)
+                                       ? " (after App Layer connect)" : "",
+                             targetPrivate->log_prefix);
+               }
+
+               success = TRUE;
+               goto done;
        }
+
        if (!_SC_CFEqual(targetPrivate->onDemandRemoteAddress, onDemandRemoteAddress) ||
            !_SC_CFEqual(targetPrivate->onDemandServiceID, onDemandServiceID)) {
                if (targetPrivate->onDemandRemoteAddress != NULL) {
@@ -4420,6 +4733,7 @@ __SCNetworkReachabilityOnDemandCheck(ReachabilityStoreInfoRef     store_info,
                }
 
                if (targetPrivate->onDemandServer != NULL) {
+                       SCNetworkReachabilitySetCallback(targetPrivate->onDemandServer, NULL, NULL);
                        if (targetPrivate->dispatchQueue != NULL) {
                                // unschedule
                                __SCNetworkReachabilityUnscheduleFromRunLoop(targetPrivate->onDemandServer, NULL, NULL, TRUE);
@@ -4446,6 +4760,7 @@ __SCNetworkReachabilityOnDemandCheck(ReachabilityStoreInfoRef     store_info,
                        targetPrivate->onDemandServiceID = NULL;
                }
        }
+
        if (ok) {
                if (onDemandStatus != kSCNetworkConnectionConnected) {
                        /*
@@ -4453,6 +4768,7 @@ __SCNetworkReachabilityOnDemandCheck(ReachabilityStoreInfoRef     store_info,
                         * bring the VPN up.  Combine our flags with those of the VPN server.
                         */
                        if (targetPrivate->onDemandServer == NULL) {
+                               SCNetworkReachabilityPrivateRef demandPrivate;
                                CFMutableDictionaryRef          options;
 
                                options = CFDictionaryCreateMutable(NULL,
@@ -4462,11 +4778,17 @@ __SCNetworkReachabilityOnDemandCheck(ReachabilityStoreInfoRef   store_info,
                                CFDictionarySetValue(options, kSCNetworkReachabilityOptionNodeName, onDemandRemoteAddress);
                                CFDictionarySetValue(options, kSCNetworkReachabilityOptionConnectionOnDemandBypass, kCFBooleanTrue);
 #ifdef HAVE_REACHABILITY_SERVER
-                               CFDictionarySetValue(options, kSCNetworkReachabilityOptionServerBypass, kCFBooleanTrue);
+                               if (targetPrivate->serverBypass) {
+                                       CFDictionarySetValue(options, kSCNetworkReachabilityOptionServerBypass, kCFBooleanTrue);
+                               }
 #endif // HAVE_REACHABILITY_SERVER
                                targetPrivate->onDemandServer = SCNetworkReachabilityCreateWithOptions(NULL, options);
                                CFRelease(options);
 
+                               // indent OnDemand target
+                               demandPrivate = (SCNetworkReachabilityPrivateRef)targetPrivate->onDemandServer;
+                               strlcat(demandPrivate->log_prefix, ".... ", sizeof(demandPrivate->log_prefix));
+
                                if (targetPrivate->scheduled) {
                                        SCNetworkReachabilityContext    context = { 0, NULL, CFRetain, CFRelease, CFCopyDescription };
 
@@ -4493,20 +4815,28 @@ __SCNetworkReachabilityOnDemandCheck(ReachabilityStoreInfoRef   store_info,
                                }
                        }
 
-                       ok = SCNetworkReachabilityGetFlags(targetPrivate->onDemandServer, flags);
                        SCLog(_sc_debug, LOG_INFO, CFSTR("%s  status  * = 0x%08x"),
                              targetPrivate->log_prefix,
                              *flags);
-                       if (ok && (*flags & kSCNetworkReachabilityFlagsReachable)) {
+
+
+                       if ((*flags & kSCNetworkReachabilityFlagsReachable) && !(*flags & kSCNetworkReachabilityFlagsConnectionRequired)) {
+                               // if VPN "server" is [still] reachable
+
                                if (!(*flags & kSCNetworkReachabilityFlagsTransientConnection)) {
-                                       // start clean if not already layered on a transient network
-                                       *flags = 0;
+                                       // start w/clean flags if not already layered on a transient network
+                                       *flags = kSCNetworkReachabilityFlagsReachable;
                                }
-                               *flags |= kSCNetworkReachabilityFlagsReachable;
+
                                *flags |= kSCNetworkReachabilityFlagsTransientConnection;
                                *flags |= kSCNetworkReachabilityFlagsConnectionRequired;
                                *flags |= kSCNetworkReachabilityFlagsConnectionOnDemand;
 
+                               // set 'InterventionRequired' if the OnDemand connection is paused
+                               if (SCNetworkConnectionIsOnDemandSuspended(connection)) {
+                                       *flags |= kSCNetworkReachabilityFlagsInterventionRequired;
+                               }
+
                                if (_sc_debug) {
                                        SCLog(TRUE, LOG_INFO, CFSTR("%s  service * = %@"),
                                              targetPrivate->log_prefix,
@@ -4515,28 +4845,140 @@ __SCNetworkReachabilityOnDemandCheck(ReachabilityStoreInfoRef  store_info,
                                              targetPrivate->log_prefix);
                                }
 
-                               onDemand = TRUE;
+                               success = TRUE;
                        }
                }
 
                if (onDemandRemoteAddress != NULL) {
                        if (targetPrivate->onDemandRemoteAddress == NULL) {
-                               targetPrivate->onDemandRemoteAddress = onDemandRemoteAddress;
-                       } else {
-                               CFRelease(onDemandRemoteAddress);
+                               targetPrivate->onDemandRemoteAddress = CFRetain(onDemandRemoteAddress);
                        }
                }
 
                if (onDemandServiceID != NULL) {
                        if (targetPrivate->onDemandServiceID == NULL) {
-                               targetPrivate->onDemandServiceID = onDemandServiceID;
-                       } else {
-                               CFRelease(onDemandServiceID);
+                               targetPrivate->onDemandServiceID = CFRetain(onDemandServiceID);
                        }
                }
        }
 
-       return onDemand;
+    done:
+
+       if (onDemandServiceID != NULL) {
+               CFRelease(onDemandServiceID);
+       }
+       if (onDemandRemoteAddress != NULL) {
+               CFRelease(onDemandRemoteAddress);
+       }
+       if (connection != NULL) {
+               CFRelease(connection);
+       }
+       if (selectOptions != NULL) {
+               CFRelease(selectOptions);
+       }
+       return success;
+}
+
+
+/*
+ * OnDemand configuration handling
+ *
+ * Notes :
+ *
+ * 1. We have a "contract" with mDNSResponder that for EVERY network
+ *    or DNS configuration change that should warrant our [re-]starting
+ *    a query, mDNSResponder will acknowledge the latest DNS configuration.
+ *
+ * 2. IPMonitor also posts a notification AFTER every network or DNS
+ *    configuration change.
+ *
+ * 3. We use IPMonitor's "trailing edge" as a signal to restart any
+ *    by-name queries.
+ */
+
+
+// Note: protected by _hn_changes_queue()
+static SCDynamicStoreCallBack  onDemand_callback               = NULL;
+static int                     onDemand_refresh_token;
+static Boolean                 onDemand_refresh_token_valid    = FALSE;
+static SCDynamicStoreRef       onDemand_store                  = NULL;
+
+
+/*
+ * onDemand_refresh_handler
+ *
+ * Called to notify/update all SCNetworkReachability targets of
+ * OnDemand changes.
+ * - caller must be running on the _hn_changes_queue()
+ */
+static void
+onDemand_refresh_handler()
+{
+       CFArrayRef      changes;
+       CFStringRef     key;
+
+       if (!onDemand_refresh_token_valid || (onDemand_callback == NULL)) {
+               return;
+       }
+
+       key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+                                                        kSCDynamicStoreDomainState,
+                                                        kSCEntNetOnDemand);
+       changes = CFArrayCreate(NULL, (const void **)&key, 1, &kCFTypeArrayCallBacks);
+       (*onDemand_callback)(onDemand_store, changes, NULL);
+       CFRelease(changes);
+       CFRelease(key);
+
+       return;
+}
+
+
+/*
+ * onDemand_refresh_enable
+ *
+ * Called to monitor for OnDemand changes.
+ * - caller must be running on the _hn_changes_queue()
+ */
+static Boolean
+onDemand_refresh_enable(dispatch_queue_t q, SCDynamicStoreRef store, SCDynamicStoreCallBack callback)
+{
+       uint32_t        status;
+
+       onDemand_callback = callback;
+       onDemand_store = CFRetain(store);
+
+       status = notify_register_dispatch(kSCNETWORKCONNECTION_ONDEMAND_NOTIFY_KEY,
+                                         &onDemand_refresh_token,
+                                         q,
+                                         ^(int token){
+                                                 onDemand_refresh_handler();
+                                         });
+       if (status != NOTIFY_STATUS_OK) {
+               SCLog(TRUE, LOG_INFO, CFSTR("notify_register_dispatch() failed, status=%lu"), status);
+               return FALSE;
+       }
+
+       onDemand_refresh_token_valid = TRUE;
+
+       return TRUE;
+}
+
+
+/*
+ * onDemand_refresh_disable
+ *
+ * Called to stop monitoring for OnDemand changes
+ * - caller must be running on the _hn_changes_queue()
+ */
+static void
+onDemand_refresh_disable()
+{
+       (void)notify_cancel(onDemand_refresh_token);
+       onDemand_refresh_token_valid = FALSE;
+       CFRelease(onDemand_store);
+       onDemand_store = NULL;
+       onDemand_callback = NULL;
+       return;
 }
 
 
@@ -4564,8 +5006,6 @@ reply_callback(int32_t status, struct addrinfo *res, void *context)
 
 static int
 getaddrinfo_interface_sync(const char                  *nodename,
-                          const char                   *servname,
-                          const struct addrinfo        *hints,
                           const char                   *interface,
                           struct addrinfo              **res)
 {
@@ -4573,8 +5013,8 @@ getaddrinfo_interface_sync(const char                     *nodename,
        reply_info      reply   = { NETDB_SUCCESS, NULL };
 
        mp = _getaddrinfo_interface_async_call(nodename,
-                                              servname,
-                                              hints,
+                                              NULL,
+                                              &HINTS_DEFAULT,
                                               interface,
                                               reply_callback,
                                               (void *)&reply);
@@ -4621,7 +5061,7 @@ getaddrinfo_interface_sync(const char                     *nodename,
        *res = reply.res;
        return reply.status;
 }
-#endif /* HAVE_GETADDRINFO_INTERFACE_ASYNC_CALL */
+#endif // HAVE_GETADDRINFO_INTERFACE_ASYNC_CALL
 
 
 static Boolean
@@ -4637,7 +5077,7 @@ __SCNetworkReachabilityGetFlags(ReachabilityStoreInfoRef  store_info,
 
        MUTEX_ASSERT_HELD(&targetPrivate->lock);
 
-       _reach_set(reach_info, &NOT_REACHABLE, reach_info->cycle);
+       _reach_set(reach_info, &NOT_REACHABLE, reach_info->cycle, targetPrivate->if_index, targetPrivate->if_name);
 
        if (!isA_SCNetworkReachability(target)) {
                _SCErrorSet(kSCStatusInvalidArgument);
@@ -4647,6 +5087,7 @@ __SCNetworkReachabilityGetFlags(ReachabilityStoreInfoRef  store_info,
 #ifdef HAVE_REACHABILITY_SERVER
        if (!targetPrivate->serverBypass) {
                if (!targetPrivate->serverActive) {
+
                        ok = __SCNetworkReachabilityServer_targetAdd(target);
                        if (!ok) {
                                targetPrivate->serverBypass = TRUE;
@@ -4663,7 +5104,11 @@ __SCNetworkReachabilityGetFlags(ReachabilityStoreInfoRef store_info,
                        }
 
                        targetPrivate->cycle = targetPrivate->serverInfo.cycle;
-                       _reach_set(&my_info, &targetPrivate->serverInfo, targetPrivate->cycle);
+                       _reach_set(&my_info,
+                                  &targetPrivate->serverInfo,
+                                  targetPrivate->serverInfo.cycle,
+                                  targetPrivate->if_index,
+                                  targetPrivate->if_name);
                        goto done;
                }
        }
@@ -4724,8 +5169,9 @@ __SCNetworkReachabilityGetFlags(ReachabilityStoreInfoRef  store_info,
                        struct timeval                  dnsQueryStart;
                        struct timeval                  dnsQueryEnd;
                        int                             error;
-                       SCNetworkReachabilityFlags      ns_flags;
-                       uint32_t                        ns_if_index;
+                       int                             ns_dns_config   = -1;
+                       SCNetworkReachabilityFlags      ns_flags        = 0;
+                       uint32_t                        ns_if_index     = 0;
                        struct addrinfo                 *res;
 
                        addresses = (CFMutableArrayRef)SCNetworkReachabilityCopyResolvedAddress(target, &error);
@@ -4733,186 +5179,100 @@ __SCNetworkReachabilityGetFlags(ReachabilityStoreInfoRef      store_info,
                                /* if resolved or an error had been detected */
                                if (!async) {
                                        /* if not an async request */
-                                       goto checkResolvedAddress;
-                               } else if (targetPrivate->llqActive) {
-                                       /* if long-lived-query active */
-                                       goto checkResolvedAddress;
+                                       goto checkResolvedAddresses;
+                               } else if (targetPrivate->dnsActive) {
+                                       /* if [m]DNS query active */
+                                       goto checkResolvedAddresses;
                                } else if ((targetPrivate->dnsMP == MACH_PORT_NULL) && !targetPrivate->needResolve) {
-                                       struct timeval          elapsed;
-                                       const struct timeval    retry_limit     = { EAI_NONAME_RETRY_LIMIT_USEC / USEC_PER_SEC,
-                                                                                   EAI_NONAME_RETRY_LIMIT_USEC % USEC_PER_SEC };
-
                                        /*
                                         * if this is an async request (i.e. someone is watching the reachability
                                         * of this target), if no query active, and if no query is needed
                                         */
-
-                                       if ((error != EAI_NONAME)
-#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
-                                           && (error != EAI_NODATA)
-#endif
-                                          ) {
-                                               /* if not "host not found" */
-                                               goto checkResolvedAddress;
-                                       }
-
-                                       /*
-                                        * if our last DNS query returned EAI_NONAME then we
-                                        * "may" want to retry.
-                                        *
-                                        * Specifically, if the [DNS] configuration was updated a while
-                                        * back then we'll trust the EAI_NONAME reply. Otherwise, we
-                                        * want to try again to ensure that we didn't get caught in a
-                                        * race between the time when the configuration was changed and
-                                        * when mDNSResponder is really ready to handle the query.
-                                        *
-                                        * Retry handling details :
-                                        *
-                                        * Compare the time when the DNS configuration was last changed and
-                                        * when our DNS reply was started (->last_dns vs ->dnsQueryStart).
-                                        *
-                                        * Expected: 0 < last_dns (t1) < dnsQueryStart (t2)
-                                        *
-                                        * last  start  end   description                        action
-                                        * ====  =====  ====  =================================  ========
-                                        *  0     N/A    N/A  no change, query error             no retry
-                                        *  0     N/A    N/A  no change, query complete          no retry
-                                        *  N/A   N/A    0    changed, query in-flight or error  no retry
-                                        *  t1 >  t2          query started, then [DNS] changed  no retry
-                                        *  t1 == t2          changed & query started together   no retry
-                                        *  t1 <  t2          changed, then query started        retry
-                                        */
-
-                                       if (!timerisset(&targetPrivate->last_dns)) {
-                                               /*
-                                                * if we have not yet seen a DNS configuration
-                                                * change
-                                                */
-                                               goto checkResolvedAddress;
-                                       }
-
-                                       if (!timerisset(&targetPrivate->dnsQueryEnd)) {
-                                               /*
-                                                * if no query end time (new request in flight)
-                                                */
-                                               goto checkResolvedAddress;
-                                       }
-
-                                       if (timercmp(&targetPrivate->last_dns,
-                                                    &targetPrivate->dnsQueryStart,
-                                                    >=)) {
-                                               /*
-                                                * if our DNS query started and then, a
-                                                * short time later, the DNS configuration
-                                                * was changed we don't need to retry
-                                                * because we will be re-issuing (and not
-                                                * retrying) the query.
-                                                */
-                                               goto checkResolvedAddress;
-                                       }
-
-                                       timersub(&targetPrivate->dnsQueryStart,
-                                                &targetPrivate->last_dns,
-                                                &elapsed);
-                                       if (timercmp(&elapsed, &retry_limit, >)) {
-                                               /*
-                                                * if the DNS query started after mDNSResponder
-                                                * had a chance to apply the last configuration
-                                                * then we should trust the EAI_NONAME reply.
-                                                */
-                                               goto checkResolvedAddress;
-                                       }
-
-                                       /* retry the DNS query */
-
-                                       if (targetPrivate->dnsRetry != NULL) {
-                                               // no need to schedule if we already have a
-                                               // retry query in flight
-                                               break;
-                                       }
-
-                                       targetPrivate->dnsRetryCount++;
-
-                                       SCLog(_sc_debug, LOG_INFO,
-                                             CFSTR("%sretry [%d] DNS query for %s%s%s%s%s"),
-                                             targetPrivate->log_prefix,
-                                             targetPrivate->dnsRetryCount,
-                                             targetPrivate->name != NULL ? "name = " : "",
-                                             targetPrivate->name != NULL ? targetPrivate->name : "",
-                                             targetPrivate->name != NULL && targetPrivate->serv != NULL ? ", " : "",
-                                             targetPrivate->serv != NULL ? "serv = " : "",
-                                             targetPrivate->serv != NULL ? targetPrivate->serv : "");
-
-                                       enqueueAsyncDNSRetry(target);
-                                       break;
+                                       goto checkResolvedAddresses;
                                }
                        }
 
                        if (!targetPrivate->onDemandBypass) {
-                               Boolean onDemand;
+                               Boolean                         onDemand;
+                               SCNetworkReachabilityFlags      onDemandFlags   = 0;
 
                                /*
                                 * before we attempt our initial DNS query, check if there is
                                 * an OnDemand configuration that we should be using.
                                 */
-                               onDemand = __SCNetworkReachabilityOnDemandCheck(store_info, target, FALSE, &my_info.flags);
+                               onDemand = __SCNetworkReachabilityOnDemandCheck(store_info, target, FALSE, &onDemandFlags);
                                if (onDemand) {
                                        /* if OnDemand connection is needed */
+                                       my_info.flags = onDemandFlags;
                                        goto done;
                                }
                        }
 
+                       targetPrivate->dnsBlocked = FALSE;
+
                        /* check the reachability of the DNS servers */
                        ok = _SC_R_checkResolverReachability(store_info,
                                                             &ns_flags,
                                                             &targetPrivate->haveDNS,
                                                             targetPrivate->name,
-                                                            targetPrivate->serv,
                                                             targetPrivate->if_index,
                                                             &ns_if_index,
-                                                            NULL,
+                                                            &ns_dns_config,
                                                             targetPrivate->log_prefix);
                        if (!ok) {
                                /* if we could not get DNS server info */
                                SCLog(_sc_debug, LOG_INFO, CFSTR("%sDNS server reachability unknown"),
                                      targetPrivate->log_prefix);
+                               targetPrivate->resolverFlags = kSCNetworkReachabilityFlagsReachable;
                                goto error;
-                       } else if (rankReachability(ns_flags) < 2) {
-                               /*
-                                * if DNS servers are not (or are no longer) reachable, set
-                                * flags based on the availability of configured (but not
-                                * active) services.
-                                */
+                       } else {
 
-                               SCLog(_sc_debug, LOG_INFO, CFSTR("%sDNS server(s) not available"),
-                                     targetPrivate->log_prefix);
+                               // save resolver reachability flags
+                               targetPrivate->resolverFlags = ns_flags;
 
-                               ok = checkAddress(store_info,
-                                                 NULL,
-                                                 targetPrivate->if_index,
-                                                 &my_info,
-                                                 targetPrivate->log_prefix);
-                               if (!ok) {
-                                       SCLog(_sc_debug, LOG_INFO, CFSTR("%sNo available networks"),
-                                             targetPrivate->log_prefix);
-                                       goto error;
-                               }
-
-                               if (async && targetPrivate->scheduled) {
+                               if (rankReachability(ns_flags) < 2) {
                                        /*
-                                        * return "host not found", set flags appropriately,
-                                        * and schedule notification.
+                                        * if DNS servers are not (or are no longer) reachable, set
+                                        * flags based on the availability of configured (but not
+                                        * active) services.
                                         */
-                                       __SCNetworkReachabilityCallbackSetResolvedAddress(EAI_NONAME,
-                                                                                         NULL,
-                                                                                         (void *)target);
-                                       my_info.flags |= (targetPrivate->info.flags & kSCNetworkReachabilityFlagsFirstResolvePending);
 
-                                       SCLog(_sc_debug, LOG_INFO, CFSTR("%sno DNS servers are reachable"),
+                                       SCLog(_sc_debug, LOG_INFO, CFSTR("%sDNS server(s) not available"),
                                              targetPrivate->log_prefix);
-                                       __SCNetworkReachabilityPerform(target);
+
+                                       if (!targetPrivate->dnsBlocked) {
+                                               ok = checkAddress(store_info,
+                                                                 NULL,
+                                                                 targetPrivate->if_index,
+                                                                 &my_info,
+                                                                 targetPrivate->log_prefix);
+                                               if (!ok) {
+                                                       SCLog(_sc_debug, LOG_INFO, CFSTR("%sNo available networks"),
+                                                             targetPrivate->log_prefix);
+                                                       goto error;
+                                               }
+                                       } else {
+                                               // if not checking "available" networks
+                                               my_info.flags = ns_flags;
+                                               my_info.if_index = ns_if_index;
+                                       }
+
+                                       if (async && targetPrivate->scheduled) {
+                                               /*
+                                                * return "host not found", set flags appropriately,
+                                                * and schedule notification.
+                                                */
+                                               __SCNetworkReachabilityCallbackSetResolvedAddresses(EAI_NONAME,
+                                                                                                   NULL,
+                                                                                                   (void *)target);
+                                               my_info.flags |= (targetPrivate->info.flags & kSCNetworkReachabilityFlagsFirstResolvePending);
+
+                                               SCLog(_sc_debug, LOG_INFO, CFSTR("%sno DNS servers are reachable"),
+                                                     targetPrivate->log_prefix);
+                                               __SCNetworkReachabilityPerformLocked(target);
+                                       }
+                                       break;
                                }
-                               break;
                        }
 
                        if (targetPrivate->resolverBypass) {
@@ -4927,118 +5287,95 @@ __SCNetworkReachabilityGetFlags(ReachabilityStoreInfoRef       store_info,
                                /* for async requests we return the last known status */
                                my_info = targetPrivate->info;
 
-                               if (targetPrivate->dnsMP != MACH_PORT_NULL) {
-                                       /* if request already in progress */
+                               if (targetPrivate->dnsActive) {
+                                       /* if [m]DNS query active */
                                        SCLog(_sc_debug, LOG_INFO,
                                              CFSTR("%swaiting for DNS reply"),
                                              targetPrivate->log_prefix);
                                        if ((addresses != NULL) || (error != NETDB_SUCCESS)) {
                                                /* updated reachability based on the previous reply */
-                                               goto checkResolvedAddress;
+                                               goto checkResolvedAddresses;
                                        }
                                        break;
                                }
 
-                               if (targetPrivate->dnsRetry != NULL) {
-                                       /* if we already have a "retry" queued */
-                                       break;
-                               }
-
-                               if (targetPrivate->llqActive) {
-                                       /* if long-lived-query active */
+                               if (targetPrivate->dnsMP != MACH_PORT_NULL) {
+                                       /* if request already in progress */
                                        SCLog(_sc_debug, LOG_INFO,
-                                             CFSTR("%swaiting for DNS updates"),
+                                             CFSTR("%swaiting for DNS* reply"),
                                              targetPrivate->log_prefix);
                                        if ((addresses != NULL) || (error != NETDB_SUCCESS)) {
                                                /* updated reachability based on the previous reply */
-                                               goto checkResolvedAddress;
+                                               goto checkResolvedAddresses;
                                        }
                                        break;
                                }
 
-                               if (!targetPrivate->llqBypass) {
-                                       SCLog(_sc_debug, LOG_INFO,
-                                             CFSTR("%sstart long-lived DNS query for %s%s%s%s%s"),
-                                             targetPrivate->log_prefix,
-                                             targetPrivate->name != NULL ? "name = " : "",
-                                             targetPrivate->name != NULL ? targetPrivate->name : "",
-                                             targetPrivate->name != NULL && targetPrivate->serv != NULL ? ", " : "",
-                                             targetPrivate->serv != NULL ? "serv = " : "",
-                                             targetPrivate->serv != NULL ? targetPrivate->serv : "");
-
-                                       /*
-                                        * initiate an long-lived DNS query
-                                        */
-                                       if (enqueueLongLivedQuery(target)) {
-                                               /* request initiated */
-                                               break;
-                                       }
-                               }
-
                                SCLog(_sc_debug, LOG_INFO,
-                                     CFSTR("%sstart DNS query for %s%s%s%s%s"),
+                                     CFSTR("%sstart DNS query for name = %s"),
                                      targetPrivate->log_prefix,
-                                     targetPrivate->name != NULL ? "name = " : "",
-                                     targetPrivate->name != NULL ? targetPrivate->name : "",
-                                     targetPrivate->name != NULL && targetPrivate->serv != NULL ? ", " : "",
-                                     targetPrivate->serv != NULL ? "serv = " : "",
-                                     targetPrivate->serv != NULL ? targetPrivate->serv : "");
+                                     targetPrivate->name);
+
+#ifdef USE_DNSSERVICEGETADDRINFO
+                               /*
+                                * initiate an DNS query w/DNSServiceGetAddrInfo
+                                */
+                               if (enqueueDNSQuery(target)) {
+                                       /* request initiated */
+                                       break;
+                               }
+#endif // USE_DNSSERVICEGETADDRINFO
 
                                /*
-                                * initiate an async DNS query
+                                * if we were unable to use DNSServiceGetAddrInfo
+                                * then try with getaddrinfo[_async_start]
                                 */
-                               if (startAsyncDNSQuery(target)) {
+                               if (enqueueAsyncDNSQuery(target)) {
                                        /* request initiated */
                                        break;
                                }
 
                                /* if we could not initiate the request, process error */
-                               goto checkResolvedAddress;
+                               goto checkResolvedAddresses;
                        }
 
                        SCLog(_sc_debug, LOG_INFO,
-                             CFSTR("%scheck DNS for %s%s%s%s%s"),
+                             CFSTR("%scheck DNS for name = %s"),
                              targetPrivate->log_prefix,
-                             targetPrivate->name != NULL ? "name = " : "",
-                             targetPrivate->name != NULL ? targetPrivate->name : "",
-                             targetPrivate->name != NULL && targetPrivate->serv != NULL ? ", " : "",
-                             targetPrivate->serv != NULL ? "serv = " : "",
-                             targetPrivate->serv != NULL ? targetPrivate->serv : "");
+                             targetPrivate->name);
 
                        /*
                         * OK, all of the DNS name servers are available.  Let's
                         * resolve the nodename into an address.
                         */
-                       __dns_query_start(&dnsQueryStart, &dnsQueryEnd);
+                       __mark_operation_start(&dnsQueryStart, &dnsQueryEnd);
 
 #ifdef HAVE_GETADDRINFO_INTERFACE_ASYNC_CALL
                        if (targetPrivate->if_index == 0) {
 #endif // HAVE_GETADDRINFO_INTERFACE_ASYNC_CALL
                                error = getaddrinfo(targetPrivate->name,
-                                                   targetPrivate->serv,
-                                                   &targetPrivate->hints,
+                                                   NULL,
+                                                   &HINTS_DEFAULT,
                                                    &res);
 #ifdef HAVE_GETADDRINFO_INTERFACE_ASYNC_CALL
                        } else {
                                error = getaddrinfo_interface_sync(targetPrivate->name,
-                                                                  targetPrivate->serv,
-                                                                  &targetPrivate->hints,
                                                                   targetPrivate->if_name,
                                                                   &res);
                        }
 #endif // HAVE_GETADDRINFO_INTERFACE_ASYNC_CALL
 
-                       __dns_query_end(target,
-                                        ((error == 0) && (res != NULL)),       // if successful query
-                                        dns_query_sync,                        // sync
-                                        &dnsQueryStart,                        // start time
-                                        &dnsQueryEnd);                         // end time
+                       __mark_operation_end(target,
+                                            ((error == 0) && (res != NULL)),   // if successful query
+                                            dns_query_sync,                    // sync
+                                            &dnsQueryStart,                    // start time
+                                            &dnsQueryEnd);                     // end time
 
-                       __SCNetworkReachabilitySetResolvedAddress(error, res, target);
+                       __SCNetworkReachabilitySetResolvedAddresses(error, res, target);
 
                        addresses = (CFMutableArrayRef)SCNetworkReachabilityCopyResolvedAddress(target, &error);
 
-                   checkResolvedAddress :
+                   checkResolvedAddresses :
 
                        /*
                         * We first assume that the requested host is NOT available.
@@ -5085,19 +5422,22 @@ __SCNetworkReachabilityGetFlags(ReachabilityStoreInfoRef        store_info,
                                         * the target host name could not be resolved
                                         */
                                        if (!targetPrivate->onDemandBypass) {
-                                               Boolean onDemand;
+                                               Boolean                         onDemand;
+                                               SCNetworkReachabilityFlags      onDemandFlags   = 0;
 
                                                /*
                                                 * our initial DNS query failed, check again to see if there
                                                 * there is an OnDemand configuration that we should be using.
                                                 */
-                                               onDemand = __SCNetworkReachabilityOnDemandCheck(store_info, target, TRUE, &my_info.flags);
+                                               onDemand = __SCNetworkReachabilityOnDemandCheck(store_info, target, TRUE, &onDemandFlags);
                                                if (onDemand) {
                                                        /* if OnDemand connection is needed */
+                                                       my_info.flags = onDemandFlags;
                                                        goto done;
                                                }
                                        }
 
+
                                        if (!targetPrivate->haveDNS) {
                                                /*
                                                 * No DNS servers are defined. Set flags based on
@@ -5134,7 +5474,8 @@ __SCNetworkReachabilityGetFlags(ReachabilityStoreInfoRef  store_info,
 
     done:
 
-       _reach_set(reach_info, &my_info, targetPrivate->cycle);
+
+       _reach_set(reach_info, &my_info, targetPrivate->cycle, targetPrivate->if_index, targetPrivate->if_name);
 
     error :
 
@@ -5143,9 +5484,8 @@ __SCNetworkReachabilityGetFlags(ReachabilityStoreInfoRef  store_info,
 }
 
 int
-SCNetworkReachabilityGetInterfaceIndex(SCNetworkReachabilityRef        target)
+SCNetworkReachabilityGetInterfaceIndex(SCNetworkReachabilityRef target)
 {
-       SCNetworkReachabilityFlags      flags;
        int                             if_index        = -1;
        Boolean                         ok              = TRUE;
        ReachabilityStoreInfo           store_info;
@@ -5162,19 +5502,17 @@ SCNetworkReachabilityGetInterfaceIndex(SCNetworkReachabilityRef target)
 
        if (targetPrivate->scheduled) {
                // if being watched, return the last known (and what should be current) status
-               flags = targetPrivate->info.flags & ~kSCNetworkReachabilityFlagsFirstResolvePending;
                goto done;
        }
 
 
        ok = __SCNetworkReachabilityGetFlags(&store_info, target, &targetPrivate->info, FALSE);
-       flags = targetPrivate->info.flags & ~kSCNetworkReachabilityFlagsFirstResolvePending;
 
     done :
 
        /* Only return the if_index if the connection is reachable not for reachable connection
         * required etc ... */
-       if (ok && rankReachability(flags) == 2) {
+       if (ok && rankReachability(targetPrivate->info.flags) == 2) {
                if_index = targetPrivate->info.if_index;
        }
 
@@ -5203,13 +5541,17 @@ SCNetworkReachabilityGetFlags(SCNetworkReachabilityRef          target,
 
        if (targetPrivate->scheduled) {
                // if being watched, return the last known (and what should be current) status
-               *flags = targetPrivate->info.flags & ~kSCNetworkReachabilityFlagsFirstResolvePending;
+               *flags = targetPrivate->info.flags & kSCNetworkReachabilityFlagsMask;
                goto done;
        }
 
 
        ok = __SCNetworkReachabilityGetFlags(&store_info, target, &targetPrivate->info, FALSE);
-       *flags = targetPrivate->info.flags & ~kSCNetworkReachabilityFlagsFirstResolvePending;
+       if (_sc_debug) {
+               SCLog(TRUE, LOG_INFO, CFSTR("%s  flags     = 0x%08x"), targetPrivate->log_prefix, targetPrivate->info.flags);
+       }
+
+       *flags = targetPrivate->info.flags & kSCNetworkReachabilityFlagsMask;
 
     done :
 
@@ -5224,7 +5566,7 @@ SCNetworkReachabilityGetFlags(SCNetworkReachabilityRef            target,
 
 
 static void
-__SCNetworkReachabilityReachabilitySetNotifications(SCDynamicStoreRef  store)
+__SCNetworkReachabilitySetNotifications(SCDynamicStoreRef      store)
 {
        CFStringRef                     key;
        CFMutableArrayRef               keys;
@@ -5234,113 +5576,117 @@ __SCNetworkReachabilityReachabilitySetNotifications(SCDynamicStoreRef store)
        keys     = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
        patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
 
-       // Setup:/Network/Global/IPv4 (for the ServiceOrder)
-       key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
-                                                        kSCDynamicStoreDomainSetup,
-                                                        kSCEntNetIPv4);
-       CFArrayAppendValue(keys, key);
-       CFRelease(key);
-
-       // State:/Network/Global/DNS
-       key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
-                                                        kSCDynamicStoreDomainState,
-                                                        kSCEntNetDNS);
-       CFArrayAppendValue(keys, key);
-       CFRelease(key);
-
-       // State:/Network/Global/IPv4 (default route)
-       key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
-                                                        kSCDynamicStoreDomainState,
-                                                        kSCEntNetIPv4);
-       CFArrayAppendValue(keys, key);
-       CFRelease(key);
-
-       // State:/Network/Global/OnDemand
-       key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
-                                                        kSCDynamicStoreDomainState,
-                                                        kSCEntNetOnDemand);
-       CFArrayAppendValue(keys, key);
-       CFRelease(key);
-
-       // Setup: per-service Interface info
-       pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
-                                                             kSCDynamicStoreDomainSetup,
-                                                             kSCCompAnyRegex,
-                                                             kSCEntNetInterface);
-       CFArrayAppendValue(patterns, pattern);
-       CFRelease(pattern);
+       // If we are bypassing nwi, then we need to get the info from the store.
+       if (D_nwiBypass) {
+               // Setup:/Network/Global/IPv4 (for the ServiceOrder)
+               key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+                                                                kSCDynamicStoreDomainSetup,
+                                                                kSCEntNetIPv4);
+               CFArrayAppendValue(keys, key);
+               CFRelease(key);
 
-       // per-service IPv4 info
-       pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
-                                                             kSCDynamicStoreDomainSetup,
-                                                             kSCCompAnyRegex,
-                                                             kSCEntNetIPv4);
-       CFArrayAppendValue(patterns, pattern);
-       CFRelease(pattern);
-       pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
-                                                             kSCDynamicStoreDomainState,
-                                                             kSCCompAnyRegex,
-                                                             kSCEntNetIPv4);
-       CFArrayAppendValue(patterns, pattern);
-       CFRelease(pattern);
+#ifndef        USE_DNSSERVICEGETADDRINFO
+               // State:/Network/Global/DNS
+               key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+                                                                kSCDynamicStoreDomainState,
+                                                                kSCEntNetDNS);
+               CFArrayAppendValue(keys, key);
+               CFRelease(key);
+#endif // USE_DNSSERVICEGETADDRINFO
 
-       // per-service IPv6 info
-       pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
-                                                             kSCDynamicStoreDomainSetup,
-                                                             kSCCompAnyRegex,
-                                                             kSCEntNetIPv6);
-       CFArrayAppendValue(patterns, pattern);
-       CFRelease(pattern);
-       pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
-                                                             kSCDynamicStoreDomainState,
-                                                             kSCCompAnyRegex,
-                                                             kSCEntNetIPv6);
-       CFArrayAppendValue(patterns, pattern);
-       CFRelease(pattern);
+               // State:/Network/Global/IPv4 (default route)
+               key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+                                                                kSCDynamicStoreDomainState,
+                                                                kSCEntNetIPv4);
+               CFArrayAppendValue(keys, key);
+               CFRelease(key);
 
-       // per-service PPP info (for existence, kSCPropNetPPPDialOnDemand, kSCPropNetPPPStatus)
-       pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
-                                                             kSCDynamicStoreDomainSetup,
-                                                             kSCCompAnyRegex,
-                                                             kSCEntNetPPP);
-       CFArrayAppendValue(patterns, pattern);
-       CFRelease(pattern);
-       pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
-                                                             kSCDynamicStoreDomainState,
-                                                             kSCCompAnyRegex,
-                                                             kSCEntNetPPP);
-       CFArrayAppendValue(patterns, pattern);
-       CFRelease(pattern);
+               // State:/Network/Global/OnDemand
+               key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+                                                                kSCDynamicStoreDomainState,
+                                                                kSCEntNetOnDemand);
+               CFArrayAppendValue(keys, key);
+               CFRelease(key);
 
-#if    !TARGET_IPHONE_SIMULATOR
-       // per-service VPN info (for existence, kSCPropNetVPNStatus)
-       pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
-                                                             kSCDynamicStoreDomainSetup,
-                                                             kSCCompAnyRegex,
-                                                             kSCEntNetVPN);
-       CFArrayAppendValue(patterns, pattern);
-       CFRelease(pattern);
-       pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
-                                                             kSCDynamicStoreDomainState,
-                                                             kSCCompAnyRegex,
-                                                             kSCEntNetVPN);
-       CFArrayAppendValue(patterns, pattern);
-       CFRelease(pattern);
-#endif // !TARGET_IPHONE_SIMULATOR
+               // Setup: per-service Interface info
+               pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+                                                                     kSCDynamicStoreDomainSetup,
+                                                                     kSCCompAnyRegex,
+                                                                     kSCEntNetInterface);
+               CFArrayAppendValue(patterns, pattern);
+               CFRelease(pattern);
+
+               // per-service IPv4 info
+               pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+                                                                     kSCDynamicStoreDomainSetup,
+                                                                     kSCCompAnyRegex,
+                                                                     kSCEntNetIPv4);
+               CFArrayAppendValue(patterns, pattern);
+               CFRelease(pattern);
+               pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+                                                                     kSCDynamicStoreDomainState,
+                                                                     kSCCompAnyRegex,
+                                                                     kSCEntNetIPv4);
+               CFArrayAppendValue(patterns, pattern);
+               CFRelease(pattern);
+
+               // per-service IPv6 info
+               pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+                                                                     kSCDynamicStoreDomainSetup,
+                                                                     kSCCompAnyRegex,
+                                                                     kSCEntNetIPv6);
+               CFArrayAppendValue(patterns, pattern);
+               CFRelease(pattern);
+               pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+                                                                     kSCDynamicStoreDomainState,
+                                                                     kSCCompAnyRegex,
+                                                                     kSCEntNetIPv6);
+               CFArrayAppendValue(patterns, pattern);
+               CFRelease(pattern);
+
+               // per-service PPP info (for existence, kSCPropNetPPPDialOnDemand, kSCPropNetPPPStatus)
+               pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+                                                                     kSCDynamicStoreDomainSetup,
+                                                                     kSCCompAnyRegex,
+                                                                     kSCEntNetPPP);
+               CFArrayAppendValue(patterns, pattern);
+               CFRelease(pattern);
+               pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+                                                                     kSCDynamicStoreDomainState,
+                                                                     kSCCompAnyRegex,
+                                                                     kSCEntNetPPP);
+               CFArrayAppendValue(patterns, pattern);
+               CFRelease(pattern);
+
+               // per-service VPN info (for existence, kSCPropNetVPNStatus)
+               pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+                                                                     kSCDynamicStoreDomainSetup,
+                                                                     kSCCompAnyRegex,
+                                                                     kSCEntNetVPN);
+               CFArrayAppendValue(patterns, pattern);
+               CFRelease(pattern);
+               pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+                                                                     kSCDynamicStoreDomainState,
+                                                                     kSCCompAnyRegex,
+                                                                     kSCEntNetVPN);
+               CFArrayAppendValue(patterns, pattern);
+               CFRelease(pattern);
+
+               // per-service IPSec info (for existence, kSCPropNetIPSecStatus)
+               pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+                                                                     kSCDynamicStoreDomainSetup,
+                                                                     kSCCompAnyRegex,
+                                                                     kSCEntNetIPSec);
+               CFArrayAppendValue(patterns, pattern);
+               CFRelease(pattern);
+               pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+                                                                     kSCDynamicStoreDomainState,
+                                                                     kSCCompAnyRegex,
+                                                                     kSCEntNetIPSec);
+               CFArrayAppendValue(patterns, pattern);
+               CFRelease(pattern);
 
-       // per-service IPSec info (for existence, kSCPropNetIPSecStatus)
-       pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
-                                                             kSCDynamicStoreDomainSetup,
-                                                             kSCCompAnyRegex,
-                                                             kSCEntNetIPSec);
-       CFArrayAppendValue(patterns, pattern);
-       CFRelease(pattern);
-       pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
-                                                             kSCDynamicStoreDomainState,
-                                                             kSCCompAnyRegex,
-                                                             kSCEntNetIPSec);
-       CFArrayAppendValue(patterns, pattern);
-       CFRelease(pattern);
+       }
 
 #if    !TARGET_OS_IPHONE
        // State: Power Management Capabilities
@@ -5351,7 +5697,6 @@ __SCNetworkReachabilityReachabilitySetNotifications(SCDynamicStoreRef     store)
        CFRelease(key);
 #endif // TARGET_OS_IPHONE
 
-
        // SCDynamicStore key to force posting a reachability change
        CFArrayAppendValue(keys, SCNETWORKREACHABILITY_TRIGGER_KEY);
 
@@ -5363,28 +5708,11 @@ __SCNetworkReachabilityReachabilitySetNotifications(SCDynamicStoreRef   store)
 }
 
 
-static dispatch_queue_t
-_hn_queue()
-{
-       static dispatch_once_t  once;
-       static dispatch_queue_t q;
-
-       dispatch_once(&once, ^{
-               q = dispatch_queue_create("SCNetworkReachabilty.changes", NULL);
-       });
-
-       return q;
-}
-
-
 static void
 __SCNetworkReachabilityHandleChanges(SCDynamicStoreRef store,
                                     CFArrayRef         changedKeys,
                                     void               *info)
 {
-#if    !TARGET_OS_IPHONE
-       Boolean                 cpuStatusChanged        = FALSE;
-#endif // !TARGET_OS_IPHONE
        Boolean                 dnsConfigChanged        = FALSE;
        CFIndex                 i;
        Boolean                 forcedChange            = FALSE;
@@ -5394,6 +5722,7 @@ __SCNetworkReachabilityHandleChanges(SCDynamicStoreRef    store,
        CFIndex                 nTargets;
        Boolean                 networkConfigChanged    = FALSE;
        struct timeval          now;
+       Boolean                 onDemandConfigChanged   = FALSE;
 #if    !TARGET_OS_IPHONE
        Boolean                 powerStatusChanged      = FALSE;
 #endif // !TARGET_OS_IPHONE
@@ -5411,7 +5740,7 @@ __SCNetworkReachabilityHandleChanges(SCDynamicStoreRef    store,
        /* "something" changed, start fresh */
        ReachabilityStoreInfo_save(NULL);
 
-       dispatch_sync(_hn_queue(), ^{
+       dispatch_sync(_hn_target_queue(), ^{
                /* grab the currently watched targets */
                if (hn_targets != NULL) {
                        watchers = CFSetCreateCopy(NULL, hn_targets);
@@ -5438,30 +5767,15 @@ __SCNetworkReachabilityHandleChanges(SCDynamicStoreRef  store,
 
                num = SCDynamicStoreCopyValue(store, key);
                if (num != NULL) {
-                       if (isA_CFNumber(num) &&
-                           CFNumberGetValue(num, kCFNumberSInt32Type, &power_capabilities)) {
-                               static Boolean  haveCPU_old     = TRUE;
-                               Boolean         haveCPU_new;
-
-                               haveCPU_new = (power_capabilities & kIOPMSystemPowerStateCapabilityCPU) != 0;
-                               if ((haveCPU_old != haveCPU_new) && haveCPU_new) {
-                                       /*
-                                        * if the power state now shows CPU availability
-                                        * then we will assume that the DNS configuration
-                                        * has changed.  This will force us to re-issue
-                                        * our DNS queries since mDNSResponder does not
-                                        * attempt to resolve names when "sleeping".
-                                        */
-                                       cpuStatusChanged = TRUE;
-                                       dnsConfigChanged = TRUE;
-                               }
-                               haveCPU_old = haveCPU_new;
-                       } else {
+                       if (!isA_CFNumber(num) ||
+                           !CFNumberGetValue(num, kCFNumberSInt32Type, &power_capabilities)) {
+                               // data not as expected, use default
                                power_capabilities = kIOPMSytemPowerStateCapabilitiesMask;
                        }
 
                        CFRelease(num);
                } else {
+                       // data not available, use default
                        power_capabilities = kIOPMSytemPowerStateCapabilitiesMask;
                }
 
@@ -5479,6 +5793,19 @@ __SCNetworkReachabilityHandleChanges(SCDynamicStoreRef   store,
        }
        CFRelease(key);
 
+       key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+                                                        kSCDynamicStoreDomainState,
+                                                        kSCEntNetOnDemand);
+       if (CFArrayContainsValue(changedKeys, CFRangeMake(0, nChanges), key)) {
+               nGlobals++;
+               onDemandConfigChanged = TRUE;   /* the OnDemand configuration has changed */
+
+               // force OnDemand configuration refresh (if SC notification arrives before BSD notify)
+               __SCNetworkConnectionForceOnDemandConfigurationRefresh();
+       }
+       CFRelease(key);
+
+
        if (CFArrayContainsValue(changedKeys, CFRangeMake(0, nChanges), SCNETWORKREACHABILITY_TRIGGER_KEY)) {
                nGlobals++;
                forcedChange = TRUE;            /* an SCDynamicStore driven "network" change */
@@ -5496,31 +5823,39 @@ __SCNetworkReachabilityHandleChanges(SCDynamicStoreRef  store,
                        "network ",
                        "DNS ",
                        "network and DNS ",
+                       "OnDemand ",
+                       "network and OnDemand ",
+                       "DNS and OnDemand ",
+                       "network, DNS, and OnDemand ",
 #if    !TARGET_OS_IPHONE
                        // with "power" status change
                        "power ",
                        "network and power ",
                        "DNS and power ",
                        "network, DNS, and power ",
-
-                       // with "power" status change (including CPU "on")
-                       "power* ",
-                       "network and power* ",
-                       "DNS and power* ",
-                       "network, DNS, and power* ",
+                       "power ",
+                       "network, OnDemand, and power ",
+                       "DNS, OnDemand, and power ",
+                       "network, DNS, OnDemand, and power ",
+                       "OnDemand and power ",
+                       "network, OnDemand, and power ",
+                       "DNS, OnDemand, and power ",
+                       "network, DNS, OnDemand, and power ",
 #endif // !TARGET_OS_IPHONE
                };
 
 #if    !TARGET_OS_IPHONE
-               #define PWR     4
+               #define PWR     8
                if (powerStatusChanged) {
                        changes |= PWR;
-                       if (cpuStatusChanged) {
-                               changes += PWR;
-                       }
                }
 #endif // !TARGET_OS_IPHONE
 
+               #define VOD     4
+               if (onDemandConfigChanged) {
+                       changes |= VOD;
+               }
+
                #define DNS     2
                if (dnsConfigChanged) {
                        changes |= DNS;
@@ -5532,7 +5867,7 @@ __SCNetworkReachabilityHandleChanges(SCDynamicStoreRef    store,
                }
 
                SCLog(TRUE, LOG_INFO,
-                     CFSTR("process %s%sconfiguration change"),
+                     CFSTR("process %s%s%sconfiguration change"),
                      forcedChange ? "[forced] " : "",
                      change_strings[changes]);
        }
@@ -5543,14 +5878,15 @@ __SCNetworkReachabilityHandleChanges(SCDynamicStoreRef  store,
                targets = CFAllocatorAllocate(NULL, nTargets * sizeof(CFTypeRef), 0);
        CFSetGetValues(watchers, targets);
        for (i = 0; i < nTargets; i++) {
+               Boolean                         dnsNeedsUpdate  = FALSE;
                SCNetworkReachabilityRef        target          = targets[i];
                SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
 
                MUTEX_LOCK(&targetPrivate->lock);
 
+
                if (dnsConfigChanged) {
                        targetPrivate->last_dns = now;
-                       targetPrivate->dnsRetryCount = 0;
                }
 
                if (networkConfigChanged) {
@@ -5564,14 +5900,19 @@ __SCNetworkReachabilityHandleChanges(SCDynamicStoreRef  store,
 #endif // !TARGET_OS_IPHONE
 
                if (targetPrivate->type == reachabilityTypeName) {
-                       Boolean         dnsChanged      = dnsConfigChanged;
+                       Boolean         dnsChanged      = (dnsConfigChanged     |
+                                                          dnsNeedsUpdate       |
+                                                          onDemandConfigChanged);
 
                        if (!dnsChanged) {
                                /*
                                 * if the DNS configuration didn't change we still need to
                                 * check that the DNS servers are accessible.
                                 */
-                               SCNetworkReachabilityFlags      ns_flags;
+                               Boolean                         ns_blocked      = FALSE;
+                               int                             ns_dns_config   = -1;
+                               SCNetworkReachabilityFlags      ns_flags        = 0;
+                               uint32_t                        ns_if_index     = 0;
                                Boolean                         ok;
 
                                /* check the reachability of the DNS servers */
@@ -5581,10 +5922,9 @@ __SCNetworkReachabilityHandleChanges(SCDynamicStoreRef   store,
                                                                             &ns_flags,
                                                                             &targetPrivate->haveDNS,
                                                                             targetPrivate->name,
-                                                                            targetPrivate->serv,
                                                                             targetPrivate->if_index,
-                                                                            NULL,
-                                                                            NULL,
+                                                                            &ns_if_index,
+                                                                            &ns_dns_config,
                                                                             targetPrivate->log_prefix);
                                }
 
@@ -5592,36 +5932,48 @@ __SCNetworkReachabilityHandleChanges(SCDynamicStoreRef  store,
                                        /* if we could not get DNS server info */
                                        SCLog(_sc_debug, LOG_INFO, CFSTR("%sDNS server reachability unknown"),
                                              targetPrivate->log_prefix);
+                                       ns_flags = kSCNetworkReachabilityFlagsReachable;
                                        dnsChanged = TRUE;
-                               } else if (rankReachability(ns_flags) < 2) {
-                                       /*
-                                        * if DNS servers are not (or are no longer) reachable, set
-                                        * flags based on the availability of configured (but not
-                                        * active) services.
-                                        */
-                                       SCLog(_sc_debug, LOG_INFO, CFSTR("%sDNS server(s) not available"),
-                                             targetPrivate->log_prefix);
+                               } else {
+
+                                       if (rankReachability(ns_flags) < 2) {
+                                               /*
+                                                * if DNS servers are not (or are no longer) reachable, set
+                                                * flags based on the availability of configured (but not
+                                                * active) services.
+                                                */
+                                               SCLog(_sc_debug, LOG_INFO, CFSTR("%sDNS server(s) not available"),
+                                                     targetPrivate->log_prefix);
+                                               dnsChanged = TRUE;
+                                       }
+                               }
+
+                               if ((targetPrivate->dnsBlocked != ns_blocked) ||
+                                   (targetPrivate->resolverFlags != ns_flags)) {
+                                       // if the DNS blocked or resolver reachability changed
+                                       targetPrivate->dnsBlocked = ns_blocked;
+                                       targetPrivate->resolverFlags = ns_flags;
                                        dnsChanged = TRUE;
                                }
                        }
 
                        if (dnsChanged) {
-                               if (targetPrivate->dnsMP != MACH_PORT_NULL) {
-                                       /* cancel the outstanding DNS query */
+                               if (targetPrivate->dnsActive) {
+                                       // if we have an outstanding [m]DNS query
                                        SCLog(_sc_debug, LOG_INFO,
-                                             CFSTR("%scancel DNS query for %s%s%s%s%s"),
+                                             CFSTR("%scancel [m]DNS query for name = %s"),
                                              targetPrivate->log_prefix,
-                                             targetPrivate->name != NULL ? "name = " : "",
-                                             targetPrivate->name != NULL ? targetPrivate->name : "",
-                                             targetPrivate->name != NULL && targetPrivate->serv != NULL ? ", " : "",
-                                             targetPrivate->serv != NULL ? "serv = " : "",
-                                             targetPrivate->serv != NULL ? targetPrivate->serv : "");
-                                       dequeueAsyncDNSQuery(target, TRUE);
+                                             targetPrivate->name);
+                                       dequeueDNSQuery(target);
                                }
 
-                               if (targetPrivate->dnsRetry != NULL) {
-                                       /* cancel the outstanding DNS retry */
-                                       dequeueAsyncDNSRetry(target);
+                               if (targetPrivate->dnsMP != MACH_PORT_NULL) {
+                                       /* if we have an outstanding [async] DNS query */
+                                       SCLog(_sc_debug, LOG_INFO,
+                                             CFSTR("%scancel DNS query for name = %s"),
+                                             targetPrivate->log_prefix,
+                                             targetPrivate->name);
+                                       dequeueAsyncDNSQuery(target, TRUE);
                                }
 
                                /* schedule request to resolve the name again */
@@ -5634,7 +5986,7 @@ __SCNetworkReachabilityHandleChanges(SCDynamicStoreRef    store,
                }
 
                if (targetPrivate->scheduled) {
-                       __SCNetworkReachabilityPerform(target);
+                       __SCNetworkReachabilityPerformLocked(target);
                }
 
                MUTEX_UNLOCK(&targetPrivate->lock);
@@ -5710,11 +6062,6 @@ reachPerform(void *info)
 
        MUTEX_LOCK(&targetPrivate->lock);
 
-       if (targetPrivate->dnsRetry != NULL) {
-               // cancel DNS retry
-               dequeueAsyncDNSRetry(target);
-       }
-
        if (!targetPrivate->scheduled) {
                // if not currently scheduled
                MUTEX_UNLOCK(&targetPrivate->lock);
@@ -5799,7 +6146,10 @@ reachPerform(void *info)
              forced ? ", forced" : "");
 
        /* update flags / interface */
-       _reach_set(&targetPrivate->info, &reach_info, cycle);
+       _reach_set(&targetPrivate->info, &reach_info, cycle, targetPrivate->if_index, targetPrivate->if_name);
+
+       /* save last notification info */
+       _reach_set(&targetPrivate->last_notify, &reach_info, cycle, targetPrivate->if_index, targetPrivate->if_name);
 
        /* as needed, defer the notification */
        if (defer) {
@@ -5807,9 +6157,6 @@ reachPerform(void *info)
                return;
        }
 
-       /* save last notification info */
-       _reach_set(&targetPrivate->last_notify, &reach_info, cycle);
-
        /* save last notification time */
        (void)gettimeofday(&targetPrivate->last_push, NULL);
 
@@ -5827,7 +6174,7 @@ reachPerform(void *info)
 
        if (rlsFunction != NULL) {
                (*rlsFunction)(target,
-                              reach_info.flags & ~kSCNetworkReachabilityFlagsFirstResolvePending,
+                              reach_info.flags & kSCNetworkReachabilityFlagsMask,
                               context_info);
        }
 
@@ -5905,6 +6252,7 @@ __SCNetworkReachabilityScheduleWithRunLoop(SCNetworkReachabilityRef       target,
 #ifdef HAVE_REACHABILITY_SERVER
        if (!targetPrivate->serverBypass) {
                if (!targetPrivate->serverActive) {
+
                        ok = __SCNetworkReachabilityServer_targetAdd(target);
                        if (!ok) {
                                targetPrivate->serverBypass = TRUE;
@@ -5925,6 +6273,7 @@ __SCNetworkReachabilityScheduleWithRunLoop(SCNetworkReachabilityRef       target,
                                goto done;
                        }
 
+
                        goto watch;
                }
        }
@@ -5932,51 +6281,86 @@ __SCNetworkReachabilityScheduleWithRunLoop(SCNetworkReachabilityRef     target,
 
        /* schedule the SCNetworkReachability did-something-change handler */
 
-       dispatch_sync(_hn_queue(), ^{
+       dispatch_sync(_hn_target_queue(), ^{
                ok = FALSE;
 
                if (!onDemand && (hn_store == NULL)) {
-                       /*
-                        * if we are not monitoring any hosts, start watching
-                        */
-                       if (!dns_configuration_watch()) {
-                               // if error
-                               _SCErrorSet(kSCStatusFailed);
-                               return;
-                       }
-
                        hn_store = SCDynamicStoreCreate(NULL,
                                                        CFSTR("SCNetworkReachability"),
                                                        __SCNetworkReachabilityHandleChanges,
                                                        NULL);
                        if (hn_store == NULL) {
                                SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreCreate() failed"));
-                               dns_configuration_unwatch();
                                return;
                        }
 
-                       __SCNetworkReachabilityReachabilitySetNotifications(hn_store);
+                       __SCNetworkReachabilitySetNotifications(hn_store);
 
-                       hn_dispatchQueue = dispatch_queue_create("SCNetworkReachabilty.changes", NULL);
-                       if (hn_dispatchQueue == NULL) {
-                               SCLog(TRUE, LOG_ERR, CFSTR("__SCNetworkReachabilityScheduleWithRunLoop dispatch_queue_create() failed"));
+                       ok = SCDynamicStoreSetDispatchQueue(hn_store, _hn_changes_queue());
+                       if (!ok) {
+                               SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreSetDispatchQueue() failed"));
                                CFRelease(hn_store);
                                hn_store = NULL;
-                               dns_configuration_unwatch();
-                               _SCErrorSet(kSCStatusFailed);
                                return;
                        }
 
-                       ok = SCDynamicStoreSetDispatchQueue(hn_store, hn_dispatchQueue);
-                       if (!ok) {
-                               SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreSetDispatchQueue() failed"));
-                               dispatch_release(hn_dispatchQueue);
-                               hn_dispatchQueue = NULL;
+                       if (!dns_configuration_watch()) {
+                               // if error
+                               SCDynamicStoreSetDispatchQueue(hn_store, NULL);
                                CFRelease(hn_store);
                                hn_store = NULL;
+                               _SCErrorSet(kSCStatusFailed);
+                               return;
+                       }
+
+#ifdef USE_DNSSERVICEGETADDRINFO
+                       if (!dns_refresh_enable(_hn_changes_queue(),
+                                               hn_store,
+                                               __SCNetworkReachabilityHandleChanges)) {
+                               // if error
                                dns_configuration_unwatch();
+                               SCDynamicStoreSetDispatchQueue(hn_store, NULL);
+                               CFRelease(hn_store);
+                               hn_store = NULL;
+                               _SCErrorSet(kSCStatusFailed);
                                return;
                        }
+#endif // USE_DNSSERVICEGETADDRINFO
+
+                       if (!D_nwiBypass) {
+                               if (!onDemand_refresh_enable(_hn_changes_queue(),
+                                                            hn_store,
+                                                            __SCNetworkReachabilityHandleChanges)) {
+                                       // if error
+                                       dns_configuration_unwatch();
+#ifdef USE_DNSSERVICEGETADDRINFO
+                                       dns_refresh_disable();
+#endif // USE_DNSSERVICEGETADDRINFO
+                                       SCDynamicStoreSetDispatchQueue(hn_store, NULL);
+                                       CFRelease(hn_store);
+                                       hn_store = NULL;
+                                       _SCErrorSet(kSCStatusFailed);
+                                       return;
+                               }
+
+                               if (!nwi_refresh_enable(_hn_changes_queue(),
+                                                       hn_store,
+                                                       __SCNetworkReachabilityHandleChanges)) {
+                                       // if error
+                                       dns_configuration_unwatch();
+#ifdef USE_DNSSERVICEGETADDRINFO
+                                       dns_refresh_disable();
+#endif // USE_DNSSERVICEGETADDRINFO
+                                       onDemand_refresh_disable();
+                                       SCDynamicStoreSetDispatchQueue(hn_store, NULL);
+                                       CFRelease(hn_store);
+                                       hn_store = NULL;
+                                       _SCErrorSet(kSCStatusFailed);
+                                       return;
+                               }
+                       }
+
+
                        hn_targets = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
 
                        ReachabilityStoreInfo_enable(TRUE);
@@ -6019,20 +6403,29 @@ __SCNetworkReachabilityScheduleWithRunLoop(SCNetworkReachabilityRef     target,
                         * are starting with a clean slate before we
                         * resolve the name
                         */
-                       if (targetPrivate->resolvedAddress != NULL) {
-                               CFRelease(targetPrivate->resolvedAddress);
-                               targetPrivate->resolvedAddress = NULL;
+                       if (targetPrivate->resolvedAddresses != NULL) {
+                               CFRelease(targetPrivate->resolvedAddresses);
+                               targetPrivate->resolvedAddresses = NULL;
                        }
-                       targetPrivate->resolvedAddressError = NETDB_SUCCESS;
+                       targetPrivate->resolvedError = NETDB_SUCCESS;
                        targetPrivate->needResolve = TRUE;
-                       _reach_set(&targetPrivate->info, &NOT_REACHABLE, targetPrivate->info.cycle);
+                       _reach_set(&targetPrivate->info,
+                                  &NOT_REACHABLE,
+                                  targetPrivate->info.cycle,
+                                  targetPrivate->if_index,
+                                  targetPrivate->if_name);
                        targetPrivate->info.flags |= kSCNetworkReachabilityFlagsFirstResolvePending;
 #ifdef HAVE_REACHABILITY_SERVER
-                       _reach_set(&targetPrivate->serverInfo, &NOT_REACHABLE, targetPrivate->serverInfo.cycle);
+                       _reach_set(&targetPrivate->serverInfo,
+                                  &NOT_REACHABLE,
+                                  targetPrivate->serverInfo.cycle,
+                                  targetPrivate->if_index,
+                                  targetPrivate->if_name);
                        targetPrivate->serverInfo.flags |= kSCNetworkReachabilityFlagsFirstResolvePending;
 #endif // HAVE_REACHABILITY_SERVER
                }
 
+
                targetPrivate->scheduled = TRUE;
 
                init = TRUE;
@@ -6095,13 +6488,25 @@ __SCNetworkReachabilityScheduleWithRunLoop(SCNetworkReachabilityRef     target,
 #ifdef HAVE_REACHABILITY_SERVER
                        reach_info.flags |= (targetPrivate->info.flags & kSCNetworkReachabilityFlagsFirstResolvePending);
 #endif // HAVE_REACHABILITY_SERVER
-                       _reach_set(&targetPrivate->info, &reach_info, targetPrivate->cycle);
-                       __SCNetworkReachabilityPerform(target);
+                       _reach_set(&targetPrivate->info,
+                                  &reach_info,
+                                  targetPrivate->cycle,
+                                  targetPrivate->if_index,
+                                  targetPrivate->if_name);
+                       __SCNetworkReachabilityPerformLocked(target);
                } else {
                        /* if reachability status not available, async lookup started */
-                       _reach_set(&targetPrivate->info, &NOT_REACHABLE, targetPrivate->cycle);
+                       _reach_set(&targetPrivate->info,
+                                  &NOT_REACHABLE,
+                                  targetPrivate->cycle,
+                                  targetPrivate->if_index,
+                                  targetPrivate->if_name);
 #ifdef HAVE_REACHABILITY_SERVER
-                       _reach_set(&targetPrivate->serverInfo, &NOT_REACHABLE, targetPrivate->cycle);
+                       _reach_set(&targetPrivate->serverInfo,
+                                  &NOT_REACHABLE,
+                                  targetPrivate->cycle,
+                                  targetPrivate->if_index,
+                                  targetPrivate->if_name);
 #endif // HAVE_REACHABILITY_SERVER
                }
                ReachabilityStoreInfo_free(&store_info);
@@ -6155,6 +6560,7 @@ __SCNetworkReachabilityUnscheduleFromRunLoop(SCNetworkReachabilityRef     target,
        // unschedule the target specific sources
        if (targetPrivate->dispatchQueue != NULL) {
                if (targetPrivate->onDemandServer != NULL) {
+                       SCNetworkReachabilitySetCallback(targetPrivate->onDemandServer, NULL, NULL);
                        __SCNetworkReachabilityUnscheduleFromRunLoop(targetPrivate->onDemandServer, NULL, NULL, TRUE);
                }
 
@@ -6186,6 +6592,9 @@ __SCNetworkReachabilityUnscheduleFromRunLoop(SCNetworkReachabilityRef     target,
 
                        if (n == 0) {
                                // if *all* notifications have been unscheduled
+                               if (targetPrivate->onDemandServer != NULL) {
+                                       SCNetworkReachabilitySetCallback(targetPrivate->onDemandServer, NULL, NULL);
+                               }
                                CFRelease(targetPrivate->rlList);
                                targetPrivate->rlList = NULL;
                                CFRunLoopSourceInvalidate(targetPrivate->rls);
@@ -6201,6 +6610,7 @@ __SCNetworkReachabilityUnscheduleFromRunLoop(SCNetworkReachabilityRef     target,
                // Cancel our request for server monitoring
                //
                if (targetPrivate->serverActive) {
+
                        ok = __SCNetworkReachabilityServer_targetUnschedule(target);
                        if (!ok) {
                                SCLog(TRUE, LOG_DEBUG,
@@ -6221,22 +6631,17 @@ __SCNetworkReachabilityUnscheduleFromRunLoop(SCNetworkReachabilityRef   target,
 #endif // HAVE_REACHABILITY_SERVER
 
        if (n == 0) {
-               if (targetPrivate->dnsMP != MACH_PORT_NULL) {
-                       // if we have an active async DNS query
-                       dequeueAsyncDNSQuery(target, TRUE);
+               if (targetPrivate->dnsActive) {
+                       // if we have an active [m]DNS query
+                       dequeueDNSQuery(target);
                }
 
-               if (targetPrivate->dnsRetry != NULL) {
-                       // if we have an outstanding DNS retry
-                       dequeueAsyncDNSRetry(target);
-               }
-
-               if (targetPrivate->llqActive) {
-                       // if we have a long-lived-query
-                       dequeueLongLivedQuery(target);
+               if (targetPrivate->dnsMP != MACH_PORT_NULL) {
+                       // if we have an active [async] DNS query
+                       dequeueAsyncDNSQuery(target, TRUE);
                }
 
-               dispatch_sync(_hn_queue(), ^{
+               dispatch_sync(_hn_target_queue(), ^{
                        CFSetRemoveValue(hn_targets, target);
 
                        if (onDemand) {
@@ -6249,8 +6654,6 @@ __SCNetworkReachabilityUnscheduleFromRunLoop(SCNetworkReachabilityRef     target,
 
                        // if we are no longer monitoring any targets
                        SCDynamicStoreSetDispatchQueue(hn_store, NULL);
-                       dispatch_release(hn_dispatchQueue);
-                       hn_dispatchQueue = NULL;
                        CFRelease(hn_store);
                        hn_store = NULL;
                        CFRelease(hn_targets);
@@ -6259,6 +6662,32 @@ __SCNetworkReachabilityUnscheduleFromRunLoop(SCNetworkReachabilityRef    target,
                        ReachabilityStoreInfo_enable(FALSE);
                        ReachabilityStoreInfo_save(NULL);
 
+
+                       if (!D_nwiBypass) {
+                               /*
+                                * until we start monitoring again, ensure that
+                                * any resources associated with tracking the
+                                * network changes (nwi) have been released.
+                                */
+                               nwi_refresh_disable();
+
+                               /*
+                                * until we start monitoring again, ensure that
+                                * any resources associated with tracking the
+                                * OnDemand configuration have been released.
+                                */
+                               onDemand_refresh_disable();
+                       }
+
+#ifdef USE_DNSSERVICEGETADDRINFO
+                       /*
+                        * until we start monitoring again, ensure that
+                        * any resources associated with restarting
+                        * [m]DNS queries have been released.
+                        */
+                       dns_refresh_disable();
+#endif // USE_DNSSERVICEGETADDRINFO
+
                        /*
                         * until we start monitoring again, ensure that
                         * any resources associated with tracking the
index f0caeaa96b9a86f0cd26b8bd78b341d4330769be..69ad3af5685c2020e7436f161757629daade55fe 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003-2012 Apple Inc. All rights reserved.
+ * Copyright (c) 2003-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -30,6 +30,7 @@
 #include <CoreFoundation/CoreFoundation.h>
 #include <CoreFoundation/CFRuntime.h>
 #include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCPrivate.h>
 #include <dispatch/dispatch.h>
 
 #include <dns_sd.h>
 #include <sys/socket.h>
 #include <net/if.h>
 
-#if    ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 50000)) && !TARGET_IPHONE_SIMULATOR
+#if    ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 50000))
 #define        HAVE_REACHABILITY_SERVER
 #include <xpc/xpc.h>
-#endif // ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 50000)) && !TARGET_IPHONE_SIMULATOR
+#endif // ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 50000))
+
+#if    ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 40000))
+#define        HAVE_GETADDRINFO_INTERFACE_ASYNC_CALL
+#endif // ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 40000))
+
+#if    ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 40000))
+#define        HAVE_IPSEC_STATUS
+#define        HAVE_VPN_STATUS
+#endif // ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 40000))
+
+
+
+#if    ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080/*FIXME*/) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 60000))
+#define USE_DNSSERVICEGETADDRINFO
+#endif // ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080/*FIXME*/) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 60000))
 
 
 #pragma mark -
 #define kSCNetworkReachabilityFlagsFirstResolvePending (1<<31)
 
 
-typedef        enum { NO = 0, YES, UNKNOWN }   lazyBoolean;
+
+#define kSCNetworkReachabilityFlagsMask                        0x00ffffff      // top 8-bits reserved for implementation
+
+
+typedef        enum {
+       NO      = 0,
+       YES,
+       UNKNOWN
+} lazyBoolean;
 
 
 typedef enum {
@@ -82,11 +106,10 @@ typedef struct {
 
        /* target host name */
        const char                      *name;
-       const char                      *serv;
-       struct addrinfo                 hints;
        Boolean                         needResolve;
-       CFArrayRef                      resolvedAddress;        /* CFArray[CFData] */
-       int                             resolvedAddressError;
+       CFArrayRef                      resolvedAddresses;      /* CFArray[CFData] */
+       int                             resolvedError;
+       SCNetworkReachabilityFlags      resolverFlags;
 
        /* [scoped routing] interface constraints */
        unsigned int                    if_index;
@@ -119,8 +142,6 @@ typedef struct {
        dispatch_source_t               dnsSource;              // for dispatch queries
        struct timeval                  dnsQueryStart;
        struct timeval                  dnsQueryEnd;
-       dispatch_source_t               dnsRetry;               // != NULL if DNS retry request queued
-       int                             dnsRetryCount;          // number of retry attempts
 
        /* [async] processing info */
        struct timeval                  last_dns;
@@ -138,10 +159,22 @@ typedef struct {
        CFStringRef                     onDemandServiceID;
 
 
-       Boolean                         llqActive;
-       Boolean                         llqBypass;
-       DNSServiceRef                   llqTarget;
-       dispatch_source_t               llqTimer;               // != NULL while waiting for first callback
+       union {
+               uint32_t                dnsFlags;
+               struct {
+                       Boolean         dnsActive     :1;       // if DNSServiceGetAddrInfo active
+
+                       Boolean         dnsHaveError  :1;       // error during query
+                       Boolean         dnsHaveV4     :1;       // have IPv4 (A) reply
+                       Boolean         dnsHaveV6     :1;       // have IPv6 (AAAA) reply
+                       Boolean         dnsHaveTimeout:1;       // no replies (A and/or AAAA)
+               };
+       };
+       CFArrayRef                      dnsAddresses;           // CFArray[CFData]
+       Boolean                         dnsBlocked;             // if DNS query blocked
+       int                             dnsError;
+       DNSServiceRef                   dnsMain;
+       DNSServiceRef                   dnsTarget;
 
 #ifdef HAVE_REACHABILITY_SERVER
        /* SCNetworkReachability server "client" info */
@@ -154,13 +187,17 @@ typedef struct {
        CFDataRef                       serverDigest;
        dispatch_group_t                serverGroup;
        Boolean                         serverInfoValid;
-       unsigned int                    serverQueryActive;      // 0 == no query active, else # waiting on group
+       unsigned int                    serverSyncQueryActive;  // 0 == no [sync] query active, else # waiting on group
        dispatch_queue_t                serverQueue;
        unsigned int                    serverReferences;       // how many [client] targets
        CFMutableDictionaryRef          serverWatchers;         // [client_id/target_id] watchers
+
+       Boolean                         useVPNAppLayer;         // if App-Layer VPN, only use client mode
 #endif // HAVE_REACHABILITY_SERVER
        Boolean                         resolverBypass;         // set this flag to bypass resolving the name
 
+
+
        /* logging */
        char                            log_prefix[32];
 
@@ -176,7 +213,12 @@ typedef struct {
 
 
 #define        REACH_SERVER_VERSION            20110323
+
+#if    !TARGET_IPHONE_SIMULATOR
 #define        REACH_SERVICE_NAME              "com.apple.SystemConfiguration.SCNetworkReachability"
+#else  // !TARGET_IPHONE_SIMULATOR
+#define        REACH_SERVICE_NAME              "com.apple.SystemConfiguration.SCNetworkReachability_sim"
+#endif // !TARGET_IPHONE_SIMULATOR
 
 // ------------------------------------------------------------
 
@@ -200,14 +242,12 @@ enum {
 };
 
 #define        REACH_TARGET_NAME               "name"                  // string
-#define        REACH_TARGET_SERV               "serv"                  // string
-#define        REACH_TARGET_HINTS              "hints"                 // data (struct addrinfo)
 #define        REACH_TARGET_IF_INDEX           "if_index"              // int64
 #define        REACH_TARGET_IF_NAME            "if_name"               // string
-#define        REACH_TARGET_LOCAL_ADDR         "localAddress"          // data (struct sockaddr)
-#define        REACH_TARGET_REMOTE_ADDR        "remoteAddress"         // data (struct sockaddr)
-#define        REACH_TARGET_ONDEMAND_BYPASS    "onDemandBypass"        // bool
-#define REACH_TARGET_RESOLVER_BYPASS   "resolverBypass"        // bool
+#define        REACH_TARGET_LOCAL_ADDR         "local_address"         // data (struct sockaddr)
+#define        REACH_TARGET_REMOTE_ADDR        "remote_address"        // data (struct sockaddr)
+#define        REACH_TARGET_ONDEMAND_BYPASS    "ondemand_bypass"       // bool
+#define REACH_TARGET_RESOLVER_BYPASS   "resolver_bypass"       // bool
 
 
 #define REACH_REQUEST_REPLY            "reply"                 // int64
@@ -233,13 +273,13 @@ enum {
        MESSAGE_REACHABILITY_STATUS     = 0x1001,
 };
 
-#define REACH_STATUS_CYCLE                     "cycle"                 // uint64
-#define REACH_STATUS_FLAGS                     "flags"                 // uint64
-#define REACH_STATUS_IF_INDEX                  "if_index"              // uint64
-#define REACH_STATUS_IF_NAME                   "if_name"               // data (char if_name[IFNAMSIZ])
-#define REACH_STATUS_RESOLVED_ADDRESS          "resolvedAddress"       // array[data]
-#define REACH_STATUS_RESOLVED_ADDRESS_ERROR    "resolvedAddressError"  // int64
-#define REACH_STATUS_SLEEPING                  "sleeping"              // bool
+#define REACH_STATUS_CYCLE             "cycle"                 // uint64
+#define REACH_STATUS_FLAGS             "flags"                 // uint64
+#define REACH_STATUS_IF_INDEX          "if_index"              // uint64
+#define REACH_STATUS_IF_NAME           "if_name"               // data (char if_name[IFNAMSIZ])
+#define REACH_STATUS_RESOLVED_ADDRESSES        "resolved_addresses"    // array[data]
+#define REACH_STATUS_RESOLVED_ERROR    "resolved_error"        // int64
+#define REACH_STATUS_SLEEPING          "sleeping"              // bool
 
 
 // ------------------------------------------------------------
@@ -255,14 +295,17 @@ _SCNetworkReachabilityCopyTargetDescription       (SCNetworkReachabilityRef       target);
 CFStringRef
 _SCNetworkReachabilityCopyTargetFlags          (SCNetworkReachabilityRef       target);
 
+void
+__SCNetworkReachabilityPerform                 (SCNetworkReachabilityRef       target);
+
+void
+__SCNetworkReachabilityPerformConcurrent       (SCNetworkReachabilityRef       target);
+
 #ifdef HAVE_REACHABILITY_SERVER
 
 dispatch_queue_t
 __SCNetworkReachability_concurrent_queue       (void);
 
-void
-__SCNetworkReachabilityPerformNoLock           (SCNetworkReachabilityRef       target);
-
 #pragma mark -
 #pragma mark [XPC] Reachability Server (client APIs)
 
@@ -284,17 +327,79 @@ __SCNetworkReachabilityServer_targetStatus        (SCNetworkReachabilityRef       target);
 Boolean
 __SCNetworkReachabilityServer_targetUnschedule (SCNetworkReachabilityRef       target);
 
+
 Boolean
 __SC_checkResolverReachabilityInternal         (SCDynamicStoreRef              *storeP,
                                                 SCNetworkReachabilityFlags     *flags,
                                                 Boolean                        *haveDNS,
                                                 const char                     *nodename,
-                                                const char                     *servname,
                                                 uint32_t                       *resolver_if_index,
                                                 int                            *dns_config_index);
 
 #endif // HAVE_REACHABILITY_SERVER
 
+static __inline__ void
+__SCNetworkReachabilityPrintFlags(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;
+}
+
+
 __END_DECLS
 
 #endif // _SCNETWORKREACHABILITYINTERNAL_H
index 1d85e4348fd484fbf2dcdc4e96817872175438a5..5a19657584f3eae3bfa6d9291bc3350ff52f0dce 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -38,6 +38,7 @@
 
 #include <pthread.h>
 
+#define EXTERNAL_ID_DOMAIN_PREFIX      "_"
 
 static CFStringRef     __SCNetworkServiceCopyDescription       (CFTypeRef cf);
 static void            __SCNetworkServiceDeallocate            (CFTypeRef cf);
@@ -100,6 +101,7 @@ __SCNetworkServiceDeallocate(CFTypeRef cf)
        if (servicePrivate->prefs != NULL) CFRelease(servicePrivate->prefs);
        if (servicePrivate->store != NULL) CFRelease(servicePrivate->store);
        if (servicePrivate->name != NULL) CFRelease(servicePrivate->name);
+       if (servicePrivate->externalIDs != NULL) CFRelease(servicePrivate->externalIDs);
 
        return;
 }
@@ -332,7 +334,7 @@ __SCNetworkServiceNextName(SCNetworkServiceRef service)
                }
        }
 
-       name = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), suffix);
+       name = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), (int)suffix);
        CFArrayAppendValue(newComponents, name);
        CFRelease(name);
 
@@ -452,6 +454,8 @@ SCNetworkServiceAddProtocolType(SCNetworkServiceRef service, CFStringRef protoco
        }
 
        protocol  = SCNetworkServiceCopyProtocol(service, protocolType);
+       assert(protocol != NULL);
+
        newEntity = _protocolTemplate(service, protocolType);
        ok = SCNetworkProtocolSetConfiguration(protocol, newEntity);
        CFRelease(newEntity);
@@ -519,6 +523,7 @@ SCNetworkServiceCopyAll(SCPreferencesRef prefs)
                        }
 
                        servicePrivate = __SCNetworkServiceCreatePrivate(NULL, prefs, keys[i], NULL);
+                       assert(servicePrivate != NULL);
                        CFArrayAppendValue(array, (SCNetworkServiceRef)servicePrivate);
                        CFRelease(servicePrivate);
                }
@@ -620,6 +625,7 @@ _SCNetworkServiceCopyActive(SCDynamicStoreRef store, CFStringRef serviceID)
        }
 
        servicePrivate = __SCNetworkServiceCreatePrivate(NULL, NULL, serviceID, NULL);
+       assert(servicePrivate != NULL);
        if (store != NULL) {
                servicePrivate->store = CFRetain(store);
        }
@@ -1130,7 +1136,7 @@ SCNetworkServiceGetName(SCNetworkServiceRef service)
                                                CFRetain(interface_name);
                                        }
                                        break;
-#if    !TARGET_OS_EMBEDDED && !TARGET_IPHONE_SIMULATOR
+#if    !TARGET_OS_IPHONE
                                case 1 :
                                        // compare the older "Built-in XXX" localized name
                                        interface_name = __SCNetworkInterfaceCopyXLocalizedDisplayName(interface);
@@ -1139,7 +1145,7 @@ SCNetworkServiceGetName(SCNetworkServiceRef service)
                                        // compare the older "Built-in XXX" non-localized name
                                        interface_name = __SCNetworkInterfaceCopyXNonLocalizedDisplayName(interface);
                                        break;
-#endif // !TARGET_OS_EMBEDDED && !TARGET_IPHONE_SIMULATOR
+#endif // !TARGET_OS_IPHONE
                                default :
                                        continue;
                        }
@@ -1709,3 +1715,130 @@ _SCNetworkServiceIsVPN(SCNetworkServiceRef service)
        return FALSE;
 }
 
+
+Boolean
+SCNetworkServiceSetExternalID(SCNetworkServiceRef service, CFStringRef identifierDomain, CFStringRef identifier)
+{
+       CFStringRef                                     prefs_path;
+       CFDictionaryRef                         service_dictionary;
+       SCNetworkServicePrivateRef      service_private         = (SCNetworkServicePrivateRef)service;
+       Boolean                                         success                         = FALSE;
+       CFStringRef                                     prefixed_domain;
+
+       if (!isA_SCNetworkService(service) || (service_private->prefs == NULL) || !isA_CFString(identifierDomain)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return FALSE;
+       }
+
+       if (identifier != NULL && !isA_CFString(identifier)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return FALSE;
+       }
+
+       prefixed_domain = CFStringCreateWithFormat(kCFAllocatorDefault, 0, CFSTR("%s%@"), EXTERNAL_ID_DOMAIN_PREFIX, identifierDomain);
+
+       prefs_path = SCPreferencesPathKeyCreateNetworkServiceEntity(kCFAllocatorDefault,
+                                                                   service_private->serviceID,
+                                                                   NULL);
+
+       service_dictionary = SCPreferencesPathGetValue(service_private->prefs, prefs_path);
+       if (isA_CFDictionary(service_dictionary) || ((service_dictionary == NULL) && (identifier != NULL))) {
+               CFMutableDictionaryRef  new_service_dictionary;
+
+               if (service_dictionary != NULL) {
+                       new_service_dictionary = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, service_dictionary);
+               } else {
+                       new_service_dictionary = CFDictionaryCreateMutable(kCFAllocatorDefault,
+                                                                          0,
+                                                                          &kCFTypeDictionaryKeyCallBacks,
+                                                                          &kCFTypeDictionaryValueCallBacks);
+               }
+
+               if (identifier != NULL) {
+                       CFDictionarySetValue(new_service_dictionary, prefixed_domain, identifier);
+               } else {
+                       CFDictionaryRemoveValue(new_service_dictionary, prefixed_domain);
+               }
+               success = SCPreferencesPathSetValue(service_private->prefs, prefs_path, new_service_dictionary);
+               CFRelease(new_service_dictionary);
+       }
+       CFRelease(prefs_path);
+
+       if (identifier != NULL) {
+           if (service_private->externalIDs == NULL) {
+                       service_private->externalIDs = CFDictionaryCreateMutable(kCFAllocatorDefault,
+                                                                                0,
+                                                                                                                                        &kCFTypeDictionaryKeyCallBacks,
+                                                                                                                                        &kCFTypeDictionaryValueCallBacks);
+           }
+           CFDictionarySetValue(service_private->externalIDs, prefixed_domain, identifier);
+       } else {
+           if (service_private->externalIDs != NULL) {
+                       CFDictionaryRemoveValue(service_private->externalIDs, prefixed_domain);
+           }
+       }
+
+       CFRelease(prefixed_domain);
+
+       if (!success) {
+               _SCErrorSet(kSCStatusFailed);
+       }
+
+       return success;
+}
+
+
+CFStringRef
+SCNetworkServiceCopyExternalID(SCNetworkServiceRef service, CFStringRef identifierDomain)
+{
+       SCNetworkServicePrivateRef      service_private         = (SCNetworkServicePrivateRef)service;
+       CFStringRef                                     identifier                      = NULL;
+       CFStringRef                                     prefixed_domain;
+
+       if (!isA_SCNetworkService(service) || (service_private->prefs == NULL) || !isA_CFString(identifierDomain)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return NULL;
+       }
+
+       prefixed_domain = CFStringCreateWithFormat(kCFAllocatorDefault, 0, CFSTR("%s%@"), EXTERNAL_ID_DOMAIN_PREFIX, identifierDomain);
+
+       if (service_private->externalIDs != NULL) {
+               identifier = CFDictionaryGetValue(service_private->externalIDs, prefixed_domain);
+               if (identifier != NULL) {
+                       CFRetain(identifier);
+               }
+       }
+
+       if (identifier == NULL) {
+               CFStringRef                     prefs_path;
+               CFDictionaryRef         service_dictionary;
+
+               prefs_path = SCPreferencesPathKeyCreateNetworkServiceEntity(kCFAllocatorDefault,
+                                                                           service_private->serviceID,
+                                                                           NULL);
+
+               service_dictionary = SCPreferencesPathGetValue(service_private->prefs, prefs_path);
+               if (isA_CFDictionary(service_dictionary)) {
+                       identifier = CFDictionaryGetValue(service_dictionary, prefixed_domain);
+                       if (identifier != NULL) {
+                               CFRetain(identifier);
+                               if (service_private->externalIDs == NULL) {
+                                       service_private->externalIDs = CFDictionaryCreateMutable(kCFAllocatorDefault,
+                                                                                                0,
+                                                                                                &kCFTypeDictionaryKeyCallBacks,
+                                                                                                &kCFTypeDictionaryValueCallBacks);
+                               }
+                               CFDictionarySetValue(service_private->externalIDs, prefixed_domain, identifier);
+                       }
+               }
+               CFRelease(prefs_path);
+       }
+
+       CFRelease(prefixed_domain);
+
+       if (identifier == NULL) {
+               _SCErrorSet(kSCStatusNoKey);
+       }
+
+       return identifier;
+}
index 126300fe820bea67e1ac3a1ee4f036a62b85dda8..41dd8d26b8365d4a3ed3cada65b8260c31ea9c9b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2007, 2009-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2007, 2009-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -201,6 +201,7 @@ _serviceOrder_add(SCNetworkSetRef set, SCNetworkServiceRef service)
        } else {
                newOrder = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
        }
+       assert(newOrder != NULL);
        n = CFArrayGetCount(newOrder);
 
        serviceID = SCNetworkServiceGetServiceID(service);
@@ -450,6 +451,7 @@ SCNetworkSetCopy(SCPreferencesRef prefs, CFStringRef setID)
        }
 
        setPrivate = __SCNetworkSetCreatePrivate(NULL, prefs, setID);
+       assert(setPrivate != NULL);
 
        // mark set as "old" (already established)
        setPrivate->established = TRUE;
@@ -517,6 +519,7 @@ SCNetworkSetCopyAll(SCPreferencesRef prefs)
                        }
 
                        setPrivate = __SCNetworkSetCreatePrivate(NULL, prefs, keys[i]);
+                       assert(setPrivate != NULL);
 
                        // mark set as "old" (already established)
                        setPrivate->established = TRUE;
@@ -534,6 +537,80 @@ SCNetworkSetCopyAll(SCPreferencesRef prefs)
 }
 
 
+CFArrayRef /* of SCNetworkInterfaceRef's */
+SCNetworkSetCopyAvailableInterfaces(SCNetworkSetRef set)
+{
+       CFMutableArrayRef       available;
+       CFMutableSetRef         excluded        = NULL;
+       int                     i;
+       CFArrayRef              interfaces;
+       int                     n_interfaces;
+       int                     n_exclusions    = 0;
+       SCPreferencesRef        prefs;
+       SCNetworkSetPrivateRef  setPrivate;
+
+       setPrivate = (SCNetworkSetPrivateRef)set;
+       prefs = setPrivate->prefs;
+
+       interfaces = _SCNetworkInterfaceCopyAllWithPreferences(prefs);
+       n_interfaces = CFArrayGetCount(interfaces);
+       if (n_interfaces == 0) {
+               return interfaces;
+       }
+
+       if (prefs != NULL) {
+               CFArrayRef      bridges = NULL;
+
+               excluded = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
+
+#if    !TARGET_OS_IPHONE
+               CFArrayRef      bonds   = NULL;
+
+               bonds = SCBondInterfaceCopyAll(prefs);
+               if (bonds != NULL) {
+                       __SCBondInterfaceListCollectMembers(bonds, excluded);
+                       CFRelease(bonds);
+               }
+#endif /* !TARGET_OS_IPHONE */
+
+               bridges = SCBridgeInterfaceCopyAll(prefs);
+               if (bridges != NULL) {
+                       __SCBridgeInterfaceListCollectMembers(bridges, excluded);
+                       CFRelease(bridges);
+               }
+
+               n_exclusions = CFSetGetCount(excluded);
+       }
+
+       if (n_exclusions == 0) {
+               if (excluded != NULL) {
+                       CFRelease(excluded);
+               }
+
+               return interfaces;
+       }
+
+       available = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+       for (i = 0; i < n_interfaces; i++) {
+               SCNetworkInterfaceRef   interface;
+
+               interface = CFArrayGetValueAtIndex(interfaces, i);
+               if (CFSetContainsValue(excluded, interface)) {
+                       // if excluded
+                       continue;
+               }
+
+               CFArrayAppendValue(available, interface);
+       }
+
+       CFRelease(interfaces);
+       CFRelease(excluded);
+
+       return available;
+}
+
+
 SCNetworkSetRef
 SCNetworkSetCopyCurrent(SCPreferencesRef prefs)
 {
@@ -555,6 +632,7 @@ SCNetworkSetCopyCurrent(SCPreferencesRef prefs)
                path = SCPreferencesPathKeyCreateSet(NULL, setID);
                if (CFEqual(path, currentID)) {
                        setPrivate = __SCNetworkSetCreatePrivate(NULL, prefs, setID);
+                       assert(setPrivate != NULL);
 
                        // mark set as "old" (already established)
                        setPrivate->established = TRUE;
@@ -674,6 +752,7 @@ SCNetworkSetCreate(SCPreferencesRef prefs)
        components = CFStringCreateArrayBySeparatingStrings(NULL, path, CFSTR("/"));
        setID = CFArrayGetValueAtIndex(components, 2);
        setPrivate = __SCNetworkSetCreatePrivate(NULL, prefs, setID);
+       assert(setPrivate != NULL);
        CFRelease(components);
 
        // mark set as "new" (not yet established)
@@ -1130,6 +1209,7 @@ add_supported_interfaces(CFMutableArrayRef interface_list, SCNetworkInterfaceRef
        return;
 }
 
+
 static CFSetRef        /* of SCNetworkInterfaceRef's */
 copyExcludedInterfaces(SCPreferencesRef prefs)
 {
@@ -1158,6 +1238,137 @@ copyExcludedInterfaces(SCPreferencesRef prefs)
 }
 
 
+#if    !TARGET_OS_IPHONE
+static SCBridgeInterfaceRef
+copyAutoBridgeInterface(SCPreferencesRef prefs, CFStringRef bridgeName)
+{
+       SCBridgeInterfaceRef    bridge          = NULL;
+       CFArrayRef              interfaces;
+
+       // exclude Bridge [member] interfaces
+       interfaces = SCBridgeInterfaceCopyAll(prefs);
+       if (interfaces != NULL) {
+               CFIndex         i;
+               CFIndex         n;
+
+               n = CFArrayGetCount(interfaces);
+               for (i = 0; i < n; i++) {
+                       SCBridgeInterfaceRef    interface;
+                       CFStringRef             name    = NULL;
+                       CFDictionaryRef         options;
+
+                       interface = CFArrayGetValueAtIndex(interfaces, i);
+                       options = SCBridgeInterfaceGetOptions(interface);
+                       if ((options != NULL) &&
+                           CFDictionaryGetValueIfPresent(options,
+                                                         CFSTR("__AUTO__"),
+                                                         (const void **)&name) &&
+                           _SC_CFEqual(name, bridgeName)) {
+                               bridge = interface;
+                               CFRetain(bridge);
+                               break;
+                       }
+               }
+
+               CFRelease(interfaces);
+       }
+
+       if (bridge == NULL) {
+               bridge = SCBridgeInterfaceCreate(prefs);
+               if (bridge != NULL) {
+                       CFMutableDictionaryRef  newOptions;
+                       Boolean                 ok;
+
+                       newOptions = CFDictionaryCreateMutable(NULL, 0,
+                                                              &kCFTypeDictionaryKeyCallBacks,
+                                                              &kCFTypeDictionaryValueCallBacks);
+                       CFDictionarySetValue(newOptions, CFSTR("__AUTO__"), bridgeName);
+                       ok = SCBridgeInterfaceSetOptions(bridge, newOptions);
+                       CFRelease(newOptions);
+                       if (!ok) {
+                               CFRelease(bridge);
+                               bridge = NULL;
+                       }
+               }
+       }
+
+       return bridge;
+}
+#endif // !TARGET_OS_IPHONE
+
+
+static CFArrayRef
+copyServices(SCNetworkSetRef set)
+{
+       CFArrayRef              services;
+       SCNetworkSetPrivateRef  setPrivate      = (SCNetworkSetPrivateRef)set;
+
+       // first, assume that we only want to add new services
+       // for those interfaces that are not represented in the
+       // current set.
+       services = SCNetworkSetCopyServices(set);
+       if ((services != NULL) && setPrivate->established) {
+               // but, if we are given an existing (or "established") set
+               // than we only want to add new services for those interfaces
+               // that are not represented in *any* set.
+               CFRelease(services);
+               services = SCNetworkServiceCopyAll(setPrivate->prefs);
+       }
+
+       return services;
+}
+
+
+#if    !TARGET_OS_IPHONE
+static CFArrayRef
+updateServices(CFArrayRef services, SCNetworkInterfaceRef interface)
+{
+       CFStringRef             bsdName;
+       CFIndex                 i;
+       CFIndex                 n;
+       CFMutableArrayRef       newServices;
+
+       if (services == NULL) {
+               return NULL;
+       }
+
+       bsdName = SCNetworkInterfaceGetBSDName(interface);
+
+       newServices = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+       n = CFArrayGetCount(services);
+       for (i = 0; i < n; i++) {
+               SCNetworkInterfaceRef           interface;
+               CFStringRef                     interfaceName;
+               SCNetworkServiceRef             newService;
+               SCNetworkServiceRef             service;
+               CFStringRef                     serviceID;
+               SCNetworkServicePrivateRef      servicePrivate;
+
+               service = CFArrayGetValueAtIndex(services, i);
+               interface = SCNetworkServiceGetInterface(service);
+               interfaceName = SCNetworkInterfaceGetBSDName(interface);
+               if (!_SC_CFEqual(interfaceName, bsdName)) {
+                       // if not a match, retain
+                       CFArrayAppendValue(newServices, service);
+                       continue;
+               }
+
+               // if a match, update
+               serviceID = SCNetworkServiceGetServiceID(service);
+               servicePrivate = (SCNetworkServicePrivateRef)service;
+               newService = SCNetworkServiceCopy(servicePrivate->prefs, serviceID);
+               if (newService != NULL) {
+                       CFArrayAppendValue(newServices, newService);
+                       CFRelease(newService);
+               }
+       }
+
+       return newServices;
+}
+#endif // !TARGET_OS_IPHONE
+
+
 static Boolean
 __SCNetworkSetEstablishDefaultConfigurationForInterfaces(SCNetworkSetRef set, CFArrayRef interfaces)
 {
@@ -1168,6 +1379,7 @@ __SCNetworkSetEstablishDefaultConfigurationForInterfaces(SCNetworkSetRef set, CF
        CFArrayRef              services;
        SCNetworkSetPrivateRef  setPrivate      = (SCNetworkSetPrivateRef)set;
        Boolean                 updated         = FALSE;
+       Boolean                 updatedIFs      = FALSE;
 
 #if    TARGET_OS_IPHONE
        CFArrayRef              orphans         = NULL;
@@ -1193,20 +1405,103 @@ __SCNetworkSetEstablishDefaultConfigurationForInterfaces(SCNetworkSetRef set, CF
        }
 #endif // TARGET_OS_IPHONE
 
-       // first, assume that we only want to add new services
-       // for those interfaces that are not represented in the
-       // current set.
-       services = SCNetworkSetCopyServices(set);
-       if ((services != NULL) && setPrivate->established) {
-               // but, if we are given an existing (or "established") set
-               // than we only want to add new services for those interfaces
-               // that are not represented in *any* set.
-               CFRelease(services);
-               services = SCNetworkServiceCopyAll(setPrivate->prefs);
-       }
+       // copy network services
+       services = copyServices(set);
 
+       // copy network interfaces to be excluded
        excluded = copyExcludedInterfaces(setPrivate->prefs);
 
+#if    !TARGET_OS_IPHONE
+       // look for interfaces that should auto-magically be added
+       // to an Ethernet bridge
+       n = (interfaces != NULL) ? CFArrayGetCount(interfaces) : 0;
+       for (i = 0; i < n; i++) {
+               SCBridgeInterfaceRef    bridge          = NULL;
+               SCNetworkInterfaceRef   interface;
+
+               interface = CFArrayGetValueAtIndex(interfaces, i);
+               if ((excluded != NULL)
+                   && CFSetContainsValue(excluded, interface)) {
+                       // if this interface is a member of a Bond or Bridge
+                       continue;
+               }
+
+               if (__SCNetworkServiceExistsForInterface(services, interface)) {
+                       // if this is not a new interface
+                       continue;
+               }
+
+               if (_SCNetworkInterfaceIsBuiltin(interface) &&
+                   _SCNetworkInterfaceIsThunderbolt(interface) &&
+                   !isA_SCBridgeInterface(interface)) {
+                       // add built-in Thunderbolt interfaces to bridge
+                       bridge = copyAutoBridgeInterface(setPrivate->prefs, CFSTR("thunderbolt-bridge"));
+               }
+
+               if (bridge != NULL) {
+                       CFIndex                 bridgeIndex;
+                       CFArrayRef              members;
+                       CFMutableArrayRef       newMembers;
+                       CFMutableSetRef         newExcluded;
+                       CFMutableArrayRef       newInterfaces;
+                       CFArrayRef              newServices;
+
+                       // track the bridge interface (if it's in our list)
+                       bridgeIndex = CFArrayGetFirstIndexOfValue(interfaces,
+                                                                 CFRangeMake(0, CFArrayGetCount(interfaces)),
+                                                                 bridge);
+
+                       // add new member interface
+                       members = SCBridgeInterfaceGetMemberInterfaces(bridge);
+                       if ((members != NULL) && (CFArrayGetCount(members) > 0)) {
+                               newMembers = CFArrayCreateMutableCopy(NULL, 0, members);
+                               updated = TRUE;         // if we're updating an existing bridge
+                       } else {
+                               newMembers = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+                       }
+                       CFArrayAppendValue(newMembers, interface);
+                       ok = SCBridgeInterfaceSetMemberInterfaces(bridge, newMembers);
+                       CFRelease(newMembers);
+                       if (!ok) {
+                               SCLog(TRUE, LOG_DEBUG,
+                                     CFSTR("could not update bridge with \"%@\": %s\n"),
+                                     SCNetworkInterfaceGetLocalizedDisplayName(interface),
+                                     SCErrorString(SCError()));
+                               CFRelease(bridge);
+                               continue;
+                       }
+
+                       // exclude the new member interface
+                       newExcluded = CFSetCreateMutableCopy(NULL, 0, excluded);
+                       CFRelease(excluded);
+                       CFSetAddValue(newExcluded, interface);
+                       excluded = newExcluded;
+
+                       // update the list of interfaces to include the [new or updated] bridge
+                       newInterfaces = CFArrayCreateMutableCopy(NULL, 0, interfaces);
+                       if (bridgeIndex != kCFNotFound) {
+                               CFArraySetValueAtIndex(newInterfaces, bridgeIndex, bridge);
+                       } else {
+                               CFArrayAppendValue(newInterfaces, bridge);
+                       }
+                       if (updatedIFs) {
+                               CFRelease(interfaces);
+                       }
+                       interfaces = newInterfaces;
+                       updatedIFs = TRUE;
+
+                       // refresh [existing] services
+                       newServices = updateServices(services, bridge);
+                       if (newServices != NULL) {
+                               CFRelease(services);
+                               services = newServices;
+                       }
+
+                       CFRelease(bridge);
+               }
+       }
+#endif // !TARGET_OS_IPHONE
+
        n = (interfaces != NULL) ? CFArrayGetCount(interfaces) : 0;
        for (i = 0; i < n; i++) {
                SCNetworkInterfaceRef   interface;
@@ -1318,6 +1613,7 @@ __SCNetworkSetEstablishDefaultConfigurationForInterfaces(SCNetworkSetRef set, CF
                }
                CFRelease(interface_list);
        }
+       if (updatedIFs)         CFRelease(interfaces);
        if (services != NULL)   CFRelease(services);
        if (excluded != NULL)   CFRelease(excluded);
 
@@ -1392,6 +1688,7 @@ SCNetworkSetEstablishDefaultInterfaceConfiguration(SCNetworkSetRef set, SCNetwor
        }
 
        interfaces = CFArrayCreate(NULL, (const void **)&interface, 1, &kCFTypeArrayCallBacks);
+       assert(interfaces != NULL);
        updated = __SCNetworkSetEstablishDefaultConfigurationForInterfaces(set, interfaces);
        CFRelease(interfaces);
 
index 2be8e9b079744504aa75ad033dcbd8454103ed71..0a86bc44807170e7ae95045cd101811640177eaa 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2011 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2006, 2011-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #include "SCNetworkSignature.h"
 #include "SCNetworkSignaturePrivate.h"
 #include <arpa/inet.h>
-
-const char * kSCNetworkSignatureActiveChangedNotifyName = NETWORK_ID_KEY ".active";
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <network/conninfo.h>
 
 #pragma mark SCNetworkSignature Supporting APIs
 
 static CFStringRef
 create_global_state_v4_key(void)
 {
-       return SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, 
+       return SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
                                                          kSCDynamicStoreDomainState,
                                                          kSCEntNetIPv4);
-       
+
 }
 
 static CFStringRef
@@ -88,26 +90,26 @@ create_ipv6_services_pattern(void)
 
 static CFDictionaryRef
 copy_services_for_address_family(CFAllocatorRef alloc,
-                                 int af)
+                                int af)
 {
-        CFDictionaryRef info;
-        CFArrayRef      patterns;
-        CFStringRef     pattern;
-        CFStringRef     prop;
-       
-        prop = (af == AF_INET) ? kSCEntNetIPv4 : kSCEntNetIPv6;
-        pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
-                                                              kSCDynamicStoreDomainState,
-                                                              kSCCompAnyRegex,
-                                                              prop);
-        patterns = CFArrayCreate(NULL,
-                                 (const void * *)&pattern, 1,
-                                 &kCFTypeArrayCallBacks);
-        CFRelease(pattern);
-        info = SCDynamicStoreCopyMultiple(NULL, NULL, patterns);
-        CFRelease(patterns);
-       
-        return (info);
+       CFDictionaryRef info;
+       CFArrayRef      patterns;
+       CFStringRef     pattern;
+       CFStringRef     prop;
+
+       prop = (af == AF_INET) ? kSCEntNetIPv4 : kSCEntNetIPv6;
+       pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+                                                             kSCDynamicStoreDomainState,
+                                                             kSCCompAnyRegex,
+                                                             prop);
+       patterns = CFArrayCreate(NULL,
+                                (const void * *)&pattern, 1,
+                                &kCFTypeArrayCallBacks);
+       CFRelease(pattern);
+       info = SCDynamicStoreCopyMultiple(NULL, NULL, patterns);
+       CFRelease(patterns);
+
+       return (info);
 }
 
 
@@ -115,7 +117,7 @@ static CF_RETURNS_RETAINED CFStringRef
 my_IPAddressToCFString(int af, const void * src_p)
 {
        char            ntopbuf[INET6_ADDRSTRLEN];
-       
+
        if (inet_ntop(af, src_p, ntopbuf, sizeof(ntopbuf)) != NULL) {
                return (CFStringCreateWithCString(NULL, ntopbuf,
                                                  kCFStringEncodingASCII));
@@ -138,7 +140,7 @@ SCNetworkSignatureCopyActiveIdentifierForAddress(CFAllocatorRef alloc,
        CFDictionaryRef         global_v4_state_dict = NULL;
        CFArrayRef              keys = NULL;
        CFArrayRef              patterns = NULL;
-       in_addr_t               s_addr; 
+       in_addr_t               s_addr;
        CFStringRef             service = NULL;
        CFDictionaryRef         service_dict = NULL;
        CFStringRef             service_id = NULL;
@@ -148,7 +150,7 @@ SCNetworkSignatureCopyActiveIdentifierForAddress(CFAllocatorRef alloc,
        /* only accept 0.0.0.0 (i.e. default) for now */
        if (addr == NULL
            || addr->sa_family != AF_INET
-           || addr->sa_len != sizeof(struct sockaddr_in)){
+           || addr->sa_len != sizeof(struct sockaddr_in)) {
                _SCErrorSet(kSCStatusInvalidArgument);
                goto done;
        }
@@ -160,18 +162,18 @@ SCNetworkSignatureCopyActiveIdentifierForAddress(CFAllocatorRef alloc,
                _SCErrorSet(kSCStatusInvalidArgument);
                goto done;
        }
-       
+
        global_state_v4_key = create_global_state_v4_key();
-       keys = CFArrayCreate(NULL, (const void * *)&global_state_v4_key, 
+       keys = CFArrayCreate(NULL, (const void * *)&global_state_v4_key,
                             1, &kCFTypeArrayCallBacks);
-       
+
        v4_service_pattern = create_ipv4_services_pattern();
        patterns = CFArrayCreate(NULL,  (const void * *)&v4_service_pattern, 1,
                                 &kCFTypeArrayCallBacks);
 
        info = SCDynamicStoreCopyMultiple(NULL, keys, patterns);
-       
-       if (info == NULL 
+
+       if (info == NULL
            || CFDictionaryGetCount(info) == 0) {
                goto done;
        }
@@ -181,22 +183,22 @@ SCNetworkSignatureCopyActiveIdentifierForAddress(CFAllocatorRef alloc,
        if (isA_CFDictionary(global_v4_state_dict) == NULL) {
                goto done;
        }
-       
+
        service_id = CFDictionaryGetValue(global_v4_state_dict,
                                           kSCDynamicStorePropNetPrimaryService);
 
        if (isA_CFString(service_id) == NULL) {
                goto done;
        }
-       
+
        service = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
                                                              kSCDynamicStoreDomainState,
                                                              service_id, kSCEntNetIPv4);
-       
+
        service_dict = CFDictionaryGetValue(info, service);
 
-       
-       if (isA_CFDictionary(service_dict) == NULL 
+
+       if (isA_CFDictionary(service_dict) == NULL
            || CFDictionaryGetCount(service_dict) == 0) {
                goto done;
        }
@@ -255,16 +257,16 @@ SCNetworkSignatureCopyActiveIdentifiers(CFAllocatorRef alloc)
        global_setup_v4_key = create_global_setup_v4_key();
        keys = CFArrayCreate(NULL, (const void * *)&global_setup_v4_key, 1,
                             &kCFTypeArrayCallBacks);
-       
+
        v4_service_pattern = create_ipv4_services_pattern();
        CFArrayAppendValue(patterns, v4_service_pattern);
-       
+
        v6_service_pattern = create_ipv6_services_pattern();
        CFArrayAppendValue(patterns, v6_service_pattern);
-       
+
        info = SCDynamicStoreCopyMultiple(NULL, keys, patterns);
-       
-       if (info == NULL 
+
+       if (info == NULL
            || CFDictionaryGetCount(info) == 0) {
                goto done;
        }
@@ -272,32 +274,32 @@ SCNetworkSignatureCopyActiveIdentifiers(CFAllocatorRef alloc)
        services_dict = CFDictionaryCreateMutableCopy(NULL, 0, info);
        /*
         * The service_dict should only contain services and once each
-        * service has been visited, it will be removed from the dictionary.    
+        * service has been visited, it will be removed from the dictionary.
         */
        CFDictionaryRemoveValue(services_dict, global_setup_v4_key);
 
        global_v4_dict = CFDictionaryGetValue(info, global_setup_v4_key);
 
        if (isA_CFDictionary(global_v4_dict) == NULL) {
-               service_order = CFDictionaryGetValue(global_v4_dict, 
+               service_order = CFDictionaryGetValue(global_v4_dict,
                                                     kSCPropNetServiceOrder);
                if (isA_CFArray(service_order) != NULL) {
                        count = CFArrayGetCount(service_order);
                }
        }
-       
+
        active = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-       
+
        range = CFRangeMake(0, 0);
 
        for (i = 0; i < count ; i++) {
                int                     j;
                CFStringRef             network_sig;
                CFStringRef             service;
-               CFStringRef             service_id; 
+               CFStringRef             service_id;
                CFDictionaryRef         service_info;
                CFStringRef             afs[2] = {kSCEntNetIPv4, kSCEntNetIPv6};
-               
+
                service_id = CFArrayGetValueAtIndex(service_order, i);
 
                if (isA_CFString(service_id) == NULL) {
@@ -308,7 +310,7 @@ SCNetworkSignatureCopyActiveIdentifiers(CFAllocatorRef alloc)
                        service = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
                                                kSCDynamicStoreDomainState,
                                                service_id, afs[j]);
-               
+
                        service_info = CFDictionaryGetValue(services_dict, service);
 
                        /* Does this service have a signature? */
@@ -337,7 +339,7 @@ SCNetworkSignatureCopyActiveIdentifiers(CFAllocatorRef alloc)
                CFDictionaryGetKeysAndValues(services_dict, NULL,
                                             (const void * *)values);
        }
-       
+
        for (i = 0; i < count; i++) {
                CFStringRef             network_sig;
                CFDictionaryRef         service_dict = (CFDictionaryRef)values[i];
@@ -349,13 +351,13 @@ SCNetworkSignatureCopyActiveIdentifiers(CFAllocatorRef alloc)
                network_sig = CFDictionaryGetValue(service_dict,
                                                   kStoreKeyNetworkSignature);
                /* Does this service have a signature? */
-               if (isA_CFString(network_sig) != NULL 
+               if (isA_CFString(network_sig) != NULL
                    && CFArrayContainsValue(active, range, network_sig) == FALSE) {
                        CFArrayAppendValue(active, network_sig);
                        range.length++;
                        network_sig = NULL;
                }
-       }               
+       }
  done:
        if (info != NULL) {
                CFRelease(info);
@@ -400,41 +402,44 @@ SCNetworkSignatureCopyIdentifierForConnectedSocket(CFAllocatorRef alloc,
        int                     af;
        int                     count;
        int                     i;
-       const void * *          keys = NULL;
+       char                    if_name[IFNAMSIZ];
+       CFStringRef             if_name_cf      = NULL;
+       conninfo_t *            info             = NULL;
+       const void * *          keys             = NULL;
 #define KEYS_STATIC_COUNT      10
        const void *            keys_static[KEYS_STATIC_COUNT];
        const void *            local_ip_p;
-       CFStringRef             local_ip_str = NULL;
-       CFStringRef             ret_signature = NULL;
-       CFDictionaryRef         service_info = NULL;
-       union {
-               struct sockaddr_in      inet;
-               struct sockaddr_in6     inet6;
-               struct sockaddr         sa;
-       }                       ss;
-       socklen_t               ss_len = sizeof(ss);
-       int                     status = kSCStatusFailed;
-
-       if (getsockname(sock_fd, &ss.sa, &ss_len) != 0) {
+       CFStringRef             local_ip_str    = NULL;
+       CFStringRef             ret_signature   = NULL;
+       CFDictionaryRef         service_info    = NULL;
+       int                     status          = kSCStatusFailed;
+
+       if (copyconninfo(sock_fd, CONNID_ANY, &info) != 0) {
                status = kSCStatusInvalidArgument;
                goto done;
        }
-       af = ss.inet.sin_family;
+       if ((info->ci_flags & CIF_CONNECTED) == 0
+           || info->ci_src == NULL) {
+           goto done;
+       }
+       af = info->ci_src->sa_family;
        switch (af) {
        case AF_INET:
                addresses_key = kSCPropNetIPv4Addresses;
-               local_ip_p = &ss.inet.sin_addr;
+               local_ip_p = &((struct sockaddr_in *)
+                              (void *)info->ci_src)->sin_addr;
                break;
        case AF_INET6:
                addresses_key = kSCPropNetIPv6Addresses;
-               local_ip_p = &ss.inet6.sin6_addr;
+               local_ip_p = &((struct sockaddr_in6 *)
+                              (void *)info->ci_src)->sin6_addr;
                break;
        default:
                status = kSCStatusInvalidArgument;
                goto done;
        }
 
-       /* find a service matching the local IP and get its network signature */
+       /* search for service with matching IP address and interface name */
        service_info = copy_services_for_address_family(alloc, af);
        if (service_info == NULL) {
                goto done;
@@ -443,6 +448,12 @@ SCNetworkSignatureCopyIdentifierForConnectedSocket(CFAllocatorRef alloc,
        if (local_ip_str == NULL) {
                goto done;
        }
+       if (info->ci_ifindex != 0
+           && if_indextoname(info->ci_ifindex, if_name) != NULL) {
+               if_name_cf
+                       = CFStringCreateWithCString(NULL, if_name,
+                                                   kCFStringEncodingASCII);
+       }
        count = CFDictionaryGetCount(service_info);
        if (count > KEYS_STATIC_COUNT) {
                keys = (const void * *)malloc(sizeof(*keys) * count);
@@ -467,6 +478,17 @@ SCNetworkSignatureCopyIdentifierForConnectedSocket(CFAllocatorRef alloc,
                        /* no signature */
                        continue;
                }
+               if (if_name_cf != NULL) {
+                       CFStringRef             this_if;
+
+                       this_if = CFDictionaryGetValue(value,
+                                                      kSCPropInterfaceName);
+                       if (isA_CFString(this_if) != NULL
+                           && !CFEqual(this_if, if_name_cf)) {
+                               /* interface name doesn't match */
+                               continue;
+                       }
+               }
                addrs = CFDictionaryGetValue(value, addresses_key);
                if (isA_CFArray(addrs) == NULL) {
                        continue;
@@ -480,6 +502,12 @@ SCNetworkSignatureCopyIdentifierForConnectedSocket(CFAllocatorRef alloc,
        }
 
  done:
+       if (info != NULL) {
+               freeconninfo(info);
+       }
+       if (if_name_cf != NULL) {
+               CFRelease(if_name_cf);
+       }
        if (local_ip_str != NULL) {
                CFRelease(local_ip_str);
        }
index 10926a62979904f7b8e717c81a3a4a6e44c5adc1..675ae3f6b10b0ac679c1f755e8715812069e17f9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2008, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2006, 2008, 2011, 2012 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -42,13 +42,6 @@ __BEGIN_DECLS
                or set of networks.
  */
 
-/*!
-       @const kSCNetworkSignatureActiveChangedNotifyName
-       @discussion The name to use with the notify(3) API's to monitor
-               when the list of active signatures changes.
- */
-extern const char * kSCNetworkSignatureActiveChangedNotifyName;
-
 /*!
        @function SCNetworkSignatureCopyActiveIdentifiers
        @discussion Find all currently active networks and return a list of
index 55219f069915d75af34d059117baa2d8e08da90d..1486b5cba9fd2cc1ab71a1b0c14afd5e468a5f0c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2011 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2006, 2011, 2012 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #ifndef _SCNETWORKSIGNATUREPRIVATE_H
 #define _SCNETWORKSIGNATUREPRIVATE_H
 
-#define NETWORK_ID_KEY         "com.apple.network.identification"
-#define kSCNetworkIdentificationPrefsKey CFSTR(NETWORK_ID_KEY ".plist")
-#define kSCNetworkIdentificationStoreKey CFSTR(NETWORK_ID_KEY)
-
-#define kStoreKeyServiceIdentifiers    CFSTR("ServiceIdentifiers")
-#define kStoreKeyActiveIdentifiers     CFSTR("ActiveIdentifiers")
-#define kStoreKeyPrimaryIPv4Identifier         CFSTR("PrimaryIPv4Identifier")
-
 #define kStoreKeyNetworkSignature      CFSTR("NetworkSignature")
 
 #endif /* _SCNETWORKSIGNATUREPRIVATE_H */
index 6f193c1712e49fb9fb0566a285bae2eeeaaca107..6418cfcd0fbdb9c68b4d32894124b03d503bc9c5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2008, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2008, 2010-2012 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -60,6 +60,13 @@ __SCPreferencesCommitChanges_helper(SCPreferencesRef prefs)
                ok = _SCSerialize(prefsPrivate->prefs, &data, NULL, NULL);
                if (!ok) {
                        status = kSCStatusFailed;
+                       if (_sc_verbose) {
+                               SCLog(TRUE, LOG_ERR,
+                                     CFSTR("SCPreferencesCommitChanges(-->helper) CFPropertyListCreateData() failed"));
+                               SCLog(TRUE, LOG_ERR,
+                                     CFSTR("  prefs = %s"),
+                                     prefsPrivate->newPath ? prefsPrivate->newPath : prefsPrivate->path);
+                       }
                        goto error;
                }
        }
index 7558a9ed5f36dbbdbe0d6917767aab0d7b2f121c..125ba24b99530a4e5cda29cb61f77a1422d3a76e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2000-2011 Apple Inc. All rights reserved.
+ * Copyright(c) 2000-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -48,6 +48,7 @@
 
 #include <fcntl.h>
 #include <pthread.h>
+#include <sandbox.h>
 #include <unistd.h>
 #include <sys/errno.h>
 
@@ -84,7 +85,7 @@ __SCPreferencesCopyDescription(CFTypeRef cf) {
                CFStringAppendFormat(result, NULL, CFSTR(", locked"));
        }
        if (prefsPrivate->helper_port != MACH_PORT_NULL) {
-               CFStringAppendFormat(result, NULL, CFSTR(", helper port = %p"), prefsPrivate->helper_port);
+               CFStringAppendFormat(result, NULL, CFSTR(", helper port = 0x%x"), prefsPrivate->helper_port);
        }
        CFStringAppendFormat(result, NULL, CFSTR("}"));
 
@@ -209,6 +210,7 @@ __SCPreferencesCreatePrivate(CFAllocatorRef allocator)
        prefsPrivate->changed                           = FALSE;
        prefsPrivate->isRoot                            = (geteuid() == 0);
        prefsPrivate->authorizationData                 = NULL;
+       prefsPrivate->authorizationRequired             = FALSE;
        prefsPrivate->helper_port                       = MACH_PORT_NULL;
 
        return prefsPrivate;
@@ -355,7 +357,7 @@ __SCPreferencesAccess_helper(SCPreferencesRef prefs)
        }
 
        if ((serverPrefs == NULL) || (serverSignature == NULL)) {
-               CFRelease(serverDict);
+               if (serverDict != NULL) CFRelease(serverDict);
                goto fail;
        }
 
@@ -390,7 +392,6 @@ __SCPreferencesCreate(CFAllocatorRef        allocator,
                      CFDataRef         authorizationData,
                      CFDictionaryRef   options)
 {
-       int                             fd              = -1;
        SCPreferencesPrivateRef         prefsPrivate;
        int                             sc_status       = kSCStatusOK;
 
@@ -426,87 +427,90 @@ __SCPreferencesCreate(CFAllocatorRef      allocator,
                goto error;
        }
 
-       /*
-        * open file
-        */
-       fd = open(prefsPrivate->path, O_RDONLY, 0644);
-       if (fd != -1) {
-               (void) close(fd);
-       } else {
-               switch (errno) {
-                       case ENOENT :
-                               /* no prefs file */
-                               if ((prefsID == NULL) || !CFStringHasPrefix(prefsID, CFSTR("/"))) {
-                                       /* if default preference ID or relative path */
-                                       if (prefsPrivate->newPath == NULL) {
-                                               /*
-                                                * we've looked in the "new" prefs directory
-                                                * without success.  Save the "new" path and
-                                                * look in the "old" prefs directory.
-                                                */
-                                               prefsPrivate->newPath = prefsPrivate->path;
-                                               goto retry;
-                                       } else {
-                                               /*
-                                                * we've looked in both the "new" and "old"
-                                                * prefs directories without success.  Use
-                                                * the "new" path.
-                                                */
-                                               CFAllocatorDeallocate(NULL, prefsPrivate->path);
-                                               prefsPrivate->path = prefsPrivate->newPath;
-                                               prefsPrivate->newPath = NULL;
-                                       }
+       if (access(prefsPrivate->path, R_OK) == 0) {
+               goto done;
+       }
+
+       switch (errno) {
+               case ENOENT :
+                       /* no prefs file */
+                       if ((prefsID == NULL) || !CFStringHasPrefix(prefsID, CFSTR("/"))) {
+                               /* if default preference ID or relative path */
+                               if (prefsPrivate->newPath == NULL) {
+                                       /*
+                                        * we've looked in the "new" prefs directory
+                                        * without success.  Save the "new" path and
+                                        * look in the "old" prefs directory.
+                                        */
+                                       prefsPrivate->newPath = prefsPrivate->path;
+                                       goto retry;
+                               } else {
+                                       /*
+                                        * we've looked in both the "new" and "old"
+                                        * prefs directories without success.  Use
+                                        * the "new" path.
+                                        */
+                                       CFAllocatorDeallocate(NULL, prefsPrivate->path);
+                                       prefsPrivate->path = prefsPrivate->newPath;
+                                       prefsPrivate->newPath = NULL;
                                }
+                       }
 
-                               /* no preference data, start fresh */
-                               sc_status = kSCStatusNoConfigFile;
+                       /* no preference data, start fresh */
+                       sc_status = kSCStatusNoConfigFile;
+                       goto done;
+               case EPERM  :
+               case EACCES :
+                       if (prefsPrivate->authorizationData != NULL) {
+                               /* no problem, we'll be using the helper */
                                goto done;
-                       case EACCES :
-                               if (prefsPrivate->authorizationData != NULL) {
-                                       /* no problem, we'll be using the helper */
-                                       goto done;
-                               }
+                       }
 
-                               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCPreferencesCreate open() failed: %s"), strerror(errno));
-                               sc_status = kSCStatusAccessError;
-                               break;
-                       default :
-                               SCLog(TRUE, LOG_ERR, CFSTR("__SCPreferencesCreate open() failed: %s"), strerror(errno));
-                               sc_status = kSCStatusFailed;
-                               break;
-               }
-               goto error;
+                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCPreferencesCreate open() failed: %s"), strerror(errno));
+                       sc_status = kSCStatusAccessError;
+                       break;
+               default :
+                       SCLog(TRUE, LOG_ERR, CFSTR("__SCPreferencesCreate open() failed: %s"), strerror(errno));
+                       sc_status = kSCStatusFailed;
+                       break;
        }
 
-    done :
+    error:
 
-       /* all OK */
+       CFRelease(prefsPrivate);
        _SCErrorSet(sc_status);
-       return prefsPrivate;
+       return NULL;
 
-    error :
+    done :
 
-       if (fd != -1) (void) close(fd);
-       CFRelease(prefsPrivate);
+       /* all OK */
        _SCErrorSet(sc_status);
-       return NULL;
+       return prefsPrivate;
 }
 
 
 __private_extern__ void
 __SCPreferencesAccess(SCPreferencesRef prefs)
 {
-       CFAllocatorRef                  allocator       = CFGetAllocator(prefs);
-       int                             fd              = -1;
-       SCPreferencesPrivateRef         prefsPrivate    = (SCPreferencesPrivateRef)prefs;
-       struct  stat                    statBuf;
+       CFAllocatorRef          allocator       = CFGetAllocator(prefs);
+       int                     fd              = -1;
+       SCPreferencesPrivateRef prefsPrivate    = (SCPreferencesPrivateRef)prefs;
+       struct stat             statBuf;
 
        if (prefsPrivate->accessed) {
                // if preference data has already been accessed
                return;
        }
 
-       fd = open(prefsPrivate->path, O_RDONLY, 0644);
+       if (!prefsPrivate->authorizationRequired) {
+               if (access(prefsPrivate->path, R_OK) == 0) {
+                       fd = open(prefsPrivate->path, O_RDONLY, 0644);
+               } else {
+                       fd = -1;
+               }
+       } else {
+               errno = EACCES;
+       }
        if (fd != -1) {
                // create signature
                if (fstat(fd, &statBuf) == -1) {
@@ -518,6 +522,7 @@ __SCPreferencesAccess(SCPreferencesRef      prefs)
                        case ENOENT :
                                /* no preference data, start fresh */
                                break;
+                       case EPERM  :
                        case EACCES :
                                if (prefsPrivate->authorizationData != NULL) {
                                        if (__SCPreferencesAccess_helper(prefs)) {
@@ -672,7 +677,7 @@ SCPreferencesCreateWithOptions(CFAllocatorRef       allocator,
                                                               &kCFTypeDictionaryValueCallBacks);
 #if    !TARGET_OS_IPHONE
                if (authorization != kSCPreferencesUseEntitlementAuthorization) {
-                       CFDataRef                       authorizationRefData;
+                       CFDataRef                       data;
                        AuthorizationExternalForm       extForm;
                        OSStatus                        os_status;
 
@@ -684,11 +689,11 @@ SCPreferencesCreateWithOptions(CFAllocatorRef     allocator,
                                return NULL;
                        }
 
-                       authorizationRefData = CFDataCreate(NULL, (const UInt8 *)extForm.bytes, sizeof(extForm.bytes));
+                       data = CFDataCreate(NULL, (const UInt8 *)extForm.bytes, sizeof(extForm.bytes));
                        CFDictionaryAddValue(authorizationDict,
                                             kSCHelperAuthAuthorization,
-                                            authorizationRefData);
-                       CFRelease(authorizationRefData);
+                                            data);
+                       CFRelease(data);
                }
 #endif
 
@@ -860,7 +865,7 @@ SCPreferencesSetCallback(SCPreferencesRef       prefs,
                (*prefsPrivate->rlsContext.release)(prefsPrivate->rlsContext.info);
        }
 
-       prefsPrivate->rlsFunction                       = callout;
+       prefsPrivate->rlsFunction                       = callout;
        prefsPrivate->rlsContext.info                   = NULL;
        prefsPrivate->rlsContext.retain                 = NULL;
        prefsPrivate->rlsContext.release                = NULL;
index bd947421ddce669a634cc0773f17895b8a5769d3..a9489ffacc5c60f6036f3bac974407c53332ea7c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2006, 2008, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2006, 2008, 2011, 2012 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -379,6 +379,8 @@ SCPreferencesPathCreateUniqueChild(SCPreferencesRef prefs,
                                     NULL, NULL, 0,
                                     &kCFTypeDictionaryKeyCallBacks,
                                     &kCFTypeDictionaryValueCallBacks);
+       assert(newDict != NULL);
+
        if (!setPath(prefs, newPath, newDict)) {
                CFRelease(newPath);
                newPath = NULL;
index aca0a16c5ea9cdefc75df21ad5a65b7a3593c618..f4ab7da4f275372bf6b35da38b4afd8fc2128356 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2001, 2003-2005, 2007-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2003-2005, 2007-2011, 2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -100,6 +100,7 @@ typedef struct {
 
        /* authorization, helper */
        CFDataRef               authorizationData;
+       Boolean                 authorizationRequired;
        mach_port_t             helper_port;
 
 } SCPreferencesPrivate, *SCPreferencesPrivateRef;
index 2690e17174ec6fc17a08d2915a3b3338b5e0039c..303ffdd19050eb779c09c34f1b6d3ef549d5848b 100644 (file)
        @header SCPreferencesPrivate
  */
 
+/*!
+       @defined kSCPreferencesOptionChangeNetworkSet
+       @abstract The SCPreferences "option" used to indicate that only the
+               current network set (location) is being changed.
+ */
+#define kSCPreferencesOptionChangeNetworkSet   CFSTR("change-network-set")     // CFBooleanRef
+
+/*!
+       @defined kSCPreferencesOptionRemoveWhenEmpty
+       @abstract The SCPreferences "option" used to indicate that the .plist
+               file should be removed when/if all keys have been removed.
+ */
 #define kSCPreferencesOptionRemoveWhenEmpty    CFSTR("remove-when-empty")      // CFBooleanRef
 
-#define kSCPreferencesWriteAuthorizationRight  "system.services.systemconfiguration.network"
+/*!
+       @defined kSCPreferencesAuthorizationRight_network_set
+       @abstract The authorization right used to control whether the current
+               network set (location) can be changed.
+ */
+#define kSCPreferencesAuthorizationRight_network_set   "system.preferences.location"
+
+/*!
+       @defined kSCPreferencesAuthorizationRight_write
+       @abstract The authorization right used to control whether the network
+               configuration can be changed.
+ */
+#define kSCPreferencesAuthorizationRight_write         "system.services.systemconfiguration.network"
 
 /*!
        @enum SCPreferencesKeyType
index 509c59e236a93fa0f7e39e337b65ebf2baecc47b..68460338761a346f82ba8c70ebba8843822ba84a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2012 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  */
 
 
+/* "server" defines */
+#if    !TARGET_IPHONE_SIMULATOR
+#define _SC_SERVER_PROG                        "configd"
+#else  // !TARGET_IPHONE_SIMULATOR
+#define _SC_SERVER_PROG                        "configd_sim"
+#endif // !TARGET_IPHONE_SIMULATOR
+
+
 /* atomic operations */
 #define _SC_ATOMIC_CMPXCHG(p, o, n)    __sync_bool_compare_and_swap((p), (o), (n))
 #define _SC_ATOMIC_INC(p)              __sync_fetch_and_add((p), 1)            // return (n++);
@@ -75,6 +83,20 @@ extern int   _sc_log;        /* 0 if SC messages should be written to stdout/stderr,
                                   1 if SC messages should be logged w/asl(3),
                                   2 if SC messages should be written to stdout/stderr AND logged */
 
+/* notify(3) keys */
+
+#if    !TARGET_IPHONE_SIMULATOR
+#define _SC_NOTIFY_PREFIX      "com.apple.system.config"
+#else  // !TARGET_IPHONE_SIMULATOR
+#define _SC_NOTIFY_PREFIX      "com.apple.iOS_Simulator.config"
+#endif // !TARGET_IPHONE_SIMULATOR
+
+#define _SC_NOTIFY_NETWORK_CHANGE      _SC_NOTIFY_PREFIX ".network_change"
+#define _SC_NOTIFY_NETWORK_CHANGE_DNS  _SC_NOTIFY_NETWORK_CHANGE ".dns"
+#define _SC_NOTIFY_NETWORK_CHANGE_NWI  _SC_NOTIFY_NETWORK_CHANGE ".nwi"
+#define _SC_NOTIFY_NETWORK_CHANGE_PROXY        _SC_NOTIFY_PREFIX ".proxy_change"
+
+
 /*!
        @group SCNetworkReachabilityCreateWithOptions #defines
        @discussion The following defines the keys and values that can
@@ -104,23 +126,6 @@ extern int _sc_log;        /* 0 if SC messages should be written to stdout/stderr,
  */
 #define kSCNetworkReachabilityOptionRemoteAddress              CFSTR("remote-address")
 
-/*!
-       @constant kSCNetworkReachabilityOptionServName
-       @discussion A CFString that will be passed to getaddrinfo(3).  An acceptable
-               value is either a decimal port number or a service name listed in
-               services(5).
- */
-#define kSCNetworkReachabilityOptionServName                   CFSTR("servname")
-
-/*!
-       @constant kSCNetworkReachabilityOptionHints
-       @discussion A CFData wrapping a "struct addrinfo" that will be passed to
-               getaddrinfo(3).  The caller can supply any of the ai_family,
-               ai_socktype, ai_protocol, and ai_flags structure elements.  All
-               other elements must be 0 or the null pointer.
- */
-#define kSCNetworkReachabilityOptionHints                      CFSTR("hints")
-
 /*!
        @constant kSCNetworkReachabilityOptionInterface
        @discussion A CFString specifying that the reachability query should be
@@ -128,6 +133,7 @@ extern int  _sc_log;        /* 0 if SC messages should be written to stdout/stderr,
  */
 #define kSCNetworkReachabilityOptionInterface                  CFSTR("interface")
 
+
 /*!
        @constant kSCNetworkReachabilityOptionConnectionOnDemandBypass
        @discussion A CFBoolean that indicates if we should bypass the VPNOnDemand
@@ -143,14 +149,6 @@ extern int _sc_log;        /* 0 if SC messages should be written to stdout/stderr,
 #define kSCNetworkReachabilityOptionResolverBypass             CFSTR("ResolverBypass")
 
 
-/*!
-       @constant kSCNetworkReachabilityOptionLongLivedQueryBypass
-       @discussion A CFBoolean that indicates if we should bypass usage of any
-               long-lived-queries (w/DNSServiceCreateConnection) when resolving
-               hostnames for this target.
- */
-#define kSCNetworkReachabilityOptionLongLivedQueryBypass       CFSTR("LongLivedQueryBypass")
-
 /*!
        @constant kSCNetworkReachabilityOptionServerBypass
        @discussion A CFBoolean that indicates if we should bypass usage of the
@@ -158,6 +156,9 @@ extern int  _sc_log;        /* 0 if SC messages should be written to stdout/stderr,
  */
 #define kSCNetworkReachabilityOptionServerBypass               CFSTR("ServerBypass")
 
+
+
+
 /*!
        @group
  */
@@ -404,7 +405,57 @@ void               SCLog                           (Boolean                condition,
                                                 CFStringRef            formatString,
                                                 ...);
 
+enum {
+       kSCLoggerFlagsNone              = 0x0,
+       kSCLoggerFlagsDefault   = 0x1,
+       kSCLoggerFlagsFile              = 0x2
+};
+typedef uint32_t       SCLoggerFlags;
+
+typedef struct SCLogger * SCLoggerRef;
+
+
+/*!
+       @function SCLoggerLog
+       @discussion Logs messages using SCLoggerRef
+       @param  logger A SCLoggerRef which keeps information about how logging
+               needs to be done. Passing NULL uses the default logger instance.
+       @param level An asl(3) logging priority. Passing the complement of a logging
+               priority (e.g. ~ASL_LEVEL_NOTICE) will result in log message lines
+               NOT being split by a "\n".
+       @param formatString The format string followed by format arguments
+       @result The specified message will be written to the system message
+               logger (See syslogd(8)). If logger is in verbose mode, the message
+               will be also written to a file specified in the ASL Module
+ */
+void           SCLoggerLog                     (SCLoggerRef    logger,
+                                                int            level,
+                                                CFStringRef    formatString,
+                                                ...)                   __OSX_AVAILABLE_STARTING(__MAC_10_8,__IPHONE_6_0);
+
+/*!
+       @function SCLoggerVLog
+       @discussion Logs messages using SCLoggerRef
+       @param logger A SCLoggerRef which keeps information about how logging
+               needs to be done. Passing NULL uses the default logger instance.
+       @param level An asl(3) logging priority. Passing the complement of a logging
+               priority (e.g. ~ASL_LEVEL_NOTICE) will result in log message lines
+               NOT being split by a "\n".
+       @param formatString The format string
+       @param args The va_list representing the arguments
+       @result The specified message will be written to the system message
+               logger (See syslogd(8)). If logger is in verbose mode, the message
+               will be also written to a file specified in the ASL Module
+ */
+void           SCLoggerVLog                    (SCLoggerRef    logger,
+                                                int            level,
+                                                CFStringRef    formatString,
+                                                va_list        args)   __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
+
 
+#ifdef USE_NEW_SCLOG
+#define SCLOG(sclogger, level, __string, ...)  SCLoggerLog(sclogger, level, CFSTR(__string), ## __VA_ARGS__)   // temporary, remove once all "old" clients have migrated
+#else
 /*!
        @function SCLOG
        @discussion Issue a log message.
@@ -426,6 +477,8 @@ void                SCLOG                           (aslclient              asl,
                                                 ...);
 
 
+#endif
+
 /*!
        @function SCPrint
        @discussion Conditionally issue a debug message.
@@ -440,6 +493,8 @@ void                SCPrint                         (Boolean                condition,
                                                 CFStringRef            formatString,
                                                 ...);
 
+
+
 /*!
        @function SCTrace
        @discussion Conditionally issue a debug message with a time stamp.
@@ -454,6 +509,35 @@ void               SCTrace                         (Boolean                condition,
                                                 CFStringRef            formatString,
                                                 ...);
 
+/*!
+       @function SCLoggerCreate
+       @discussion Create a reference to logger which stores information like verbose mode or not, loggerID, etc.
+                       loggerID and moduleName both need to be non NULL, or else the function returns NULL.
+                       If the moduleName points to a module which doesn't exist, then SCLoggerCreate will fail and
+                       return NULL;
+       @param loggerID CFStringRef which will be appended to the log message when in verbose mode. It will also be
+                       used to identify the module where the rules are being defined.
+ */
+SCLoggerRef
+SCLoggerCreate                                 (CFStringRef loggerID);
+
+/*!
+       @function SCLoggerGetFlags
+       @discussion Returns the log flags for the logging reference
+       @param  logger Reference which points to the logger information
+ */
+SCLoggerFlags
+SCLoggerGetFlags                               (SCLoggerRef logger);
+
+/*!
+       @function SCLoggerSetFlags
+       @discussion Sets the log flags for the logger reference
+       @param  logger A reference to the logger
+       @param  flags SCLoggerFlags value determining where the logs from the logger will be directed
+ */
+void           SCLoggerSetFlags                (SCLoggerRef logger,
+                                                SCLoggerFlags flags);
+
 #pragma mark -
 #pragma mark Proxies
 
@@ -479,6 +563,29 @@ SCNetworkProxiesCopyMatching                       (CFDictionaryRef        globalConfiguration,
                                                 CFStringRef            server,
                                                 CFStringRef            interface)      __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_5_0/*SPI*/);
 
+extern const CFStringRef       kSCProxiesNoGlobal;
+
+/*!
+ @function SCDynamicStoreCopyProxiesWithOptions
+ @discussion
+
+       @param  store An SCDynamicStoreRef representing the dynamic store
+               session that should be used for communication with the server.
+               If NULL, a temporary session will be used.
+       @param  options  A dictionary of proxy options which can include 1 (or more) of the following :
+               key                             value           description
+               ---------------------------------------------------------------------------------------
+               kSCProxiesNoGlobal              CFBoolean       Bypass any "global" proxy configuration
+               ...
+       @result Returns a dictionary containing key-value pairs that represent
+               the current internet proxy settings;
+               NULL if no proxy settings have been defined or if an error
+               was encountered.
+               You must release the returned value.
+*/
+CFDictionaryRef
+SCDynamicStoreCopyProxiesWithOptions(SCDynamicStoreRef store, CFDictionaryRef options) __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/);
+
 #pragma mark -
 #pragma mark Reachability
 
@@ -546,9 +653,9 @@ _SC_checkResolverReachabilityByAddress              (SCDynamicStoreRef              *storeP,
 int
 SCNetworkReachabilityGetInterfaceIndex         (SCNetworkReachabilityRef       target);
 
+
 #pragma mark -
 #pragma mark Domain
-
 /*!
        @function    _SC_domainEndsWithDomain
        @discussion  Checks if one domain is a subset of another
@@ -728,6 +835,13 @@ _SC_crash                                  (const char             *crash_info,
                                                 CFStringRef            notifyHeader,
                                                 CFStringRef            notifyMessage);
 
+Boolean
+_SC_getconninfo                                        (int                            socket,
+                                                struct sockaddr_storage        *src_addr,
+                                                struct sockaddr_storage        *dest_addr,
+                                                int                            *if_index,
+                                                uint32_t                       *flags);
+
 __END_DECLS
 
 #endif /* _SCPRIVATE_H */
index b041e3cc94da3005de289bd25e85c72890130fe4..9fe060d92d35bbe7e01ac750ba66721d6227ef41 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2004, 2006-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2004, 2006-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -32,6 +32,7 @@
 #include <SystemConfiguration/SystemConfiguration.h>
 #include <SystemConfiguration/SCValidation.h>
 #include <SystemConfiguration/SCPrivate.h>
+#include <SystemConfiguration/VPNAppLayerPrivate.h>
 
 #include <netdb.h>
 
@@ -62,8 +63,7 @@ validate_proxy_content(CFMutableDictionaryRef proxies,
        if (num != NULL) {
                if (!isA_CFNumber(num) ||
                    !CFNumberGetValue(num, kCFNumberIntType, &enabled)) {
-                       // if we don't like the enabled key/value
-                       goto disable;
+                       goto disable;           // if we don't like the enabled key/value
                }
        }
 
@@ -71,26 +71,38 @@ validate_proxy_content(CFMutableDictionaryRef       proxies,
                CFStringRef     host;
 
                host = CFDictionaryGetValue(proxies, proxy_host);
-               if (((enabled == 0) && (host != NULL)) ||
-                   ((enabled != 0) && !isA_CFString(host))) {
-                       // pass only valid proxy hosts and only when enabled
-                       goto disable;
+               if ((enabled == 0) && (host != NULL)) {
+                       goto disable;           // if not enabled, remove provided key/value
+               }
+
+               if ((enabled != 0) && !isA_CFString(host)) {
+                       goto disable;           // if enabled, not provided (or not valid)
                }
        }
 
        if (proxy_port != NULL) {
                CFNumberRef     port;
+               int             s_port  = 0;
 
                port = CFDictionaryGetValue(proxies, proxy_port);
-               if (((enabled == 0) && (port != NULL)) ||
-                   ((enabled != 0) && (port != NULL) && !isA_CFNumber(port))) {
-                       // pass only provided/valid proxy ports and only when enabled
-                       goto disable;
+               if ((enabled == 0) && (port != NULL)) {
+                       goto disable;           // if not enabled, remove provided key/value
+               }
+
+               if ((enabled != 0) && (port != NULL)) {
+                       if (!isA_CFNumber(port) ||
+                           !CFNumberGetValue(port, kCFNumberIntType, &s_port) ||
+                           (s_port > UINT16_MAX)) {
+                               goto disable;   // if enabled, not provided (or not valid)
+                       }
+
+                       if (s_port == 0) {
+                               port = NULL;    // if no port # provided, use default
+                       }
                }
 
                if ((enabled != 0) && (port == NULL)) {
                        struct servent  *service;
-                       int             s_port;
 
                        service = getservbyname(proxy_service, "tcp");
                        if (service != NULL) {
@@ -127,6 +139,10 @@ static void
 normalize_scoped_proxy(const void *key, const void *value, void *context);
 
 
+static void
+normalize_services_proxy(const void *key, const void *value, void *context);
+
+
 static void
 normalize_supplemental_proxy(const void *value, void *context);
 
@@ -138,6 +154,7 @@ __SCNetworkProxiesCopyNormalized(CFDictionaryRef proxy)
        CFMutableDictionaryRef  newProxy;
        CFNumberRef             num;
        CFDictionaryRef         scoped;
+       CFDictionaryRef         services;
        CFArrayRef              supplemental;
 
        if (!isA_CFDictionary(proxy)) {
@@ -213,6 +230,13 @@ __SCNetworkProxiesCopyNormalized(CFDictionaryRef proxy)
                               NULL,
                               0);
 
+       validate_proxy_content(newProxy,
+                              kSCPropNetProxiesFallBackAllowed,
+                              NULL,
+                              NULL,
+                              NULL,
+                              0);
+
        // validate FTP passive setting
        num = CFDictionaryGetValue(newProxy, kSCPropNetProxiesFTPPassive);
        if (num != NULL) {
@@ -286,6 +310,22 @@ __SCNetworkProxiesCopyNormalized(CFDictionaryRef proxy)
                CFRelease(newScoped);
        }
 
+       // cleanup services proxies
+       services = CFDictionaryGetValue(newProxy, kSCPropNetProxiesServices);
+       if (isA_CFDictionary(services)) {
+               CFMutableDictionaryRef  newServices;
+
+               newServices = CFDictionaryCreateMutable(NULL,
+                                                     0,
+                                                     &kCFTypeDictionaryKeyCallBacks,
+                                                     &kCFTypeDictionaryValueCallBacks);
+               CFDictionaryApplyFunction(services,
+                                         normalize_services_proxy,
+                                         newServices);
+               CFDictionarySetValue(newProxy, kSCPropNetProxiesServices, newServices);
+               CFRelease(newServices);
+       }
+
        // cleanup split/supplemental proxies
        supplemental = CFDictionaryGetValue(newProxy, kSCPropNetProxiesSupplemental);
        if (isA_CFArray(supplemental)) {
@@ -323,6 +363,19 @@ normalize_scoped_proxy(const void *key, const void *value, void *context)
        return;
 }
 
+static void
+normalize_services_proxy(const void *key, const void *value, void *context)
+{
+       CFStringRef             serviceID       = (CFStringRef)key;
+       CFDictionaryRef         proxy           = (CFDictionaryRef)value;
+       CFMutableDictionaryRef  newServices     = (CFMutableDictionaryRef)context;
+
+       proxy = __SCNetworkProxiesCopyNormalized(proxy);
+       CFDictionarySetValue(newServices, serviceID, proxy);
+       CFRelease(proxy);
+
+       return;
+}
 
 static void
 normalize_supplemental_proxy(const void *value, void *context)
@@ -337,13 +390,35 @@ normalize_supplemental_proxy(const void *value, void *context)
        return;
 }
 
-
 CFDictionaryRef
 SCDynamicStoreCopyProxies(SCDynamicStoreRef store)
 {
+       return SCDynamicStoreCopyProxiesWithOptions(store, NULL);
+}
+
+const CFStringRef      kSCProxiesNoGlobal      = CFSTR("NO_GLOBAL");
+
+CFDictionaryRef
+SCDynamicStoreCopyProxiesWithOptions(SCDynamicStoreRef store, CFDictionaryRef options)
+{
+       Boolean                 bypass  = FALSE;
        CFStringRef             key;
        CFDictionaryRef         proxies;
 
+       if (options != NULL) {
+               CFBooleanRef    bypassGlobalOption;
+
+               if (isA_CFDictionary(options) == NULL) {
+                       _SCErrorSet(kSCStatusInvalidArgument);
+                       return NULL;
+               }
+
+               bypassGlobalOption = CFDictionaryGetValue(options, kSCProxiesNoGlobal);
+               if (isA_CFBoolean(bypassGlobalOption) && CFBooleanGetValue(bypassGlobalOption)) {
+                       bypass = TRUE;
+               }
+       }
+
 
        /* copy proxy information from dynamic store */
 
@@ -376,11 +451,14 @@ SCNetworkProxiesCopyMatching(CFDictionaryRef      globalConfiguration,
                             CFStringRef        server,
                             CFStringRef        interface)
 {
-       CFMutableDictionaryRef  newProxy;
-       CFArrayRef              proxies         = NULL;
-       CFDictionaryRef         proxy;
-       int                     sc_status       = kSCStatusOK;
-       CFStringRef             trimmed         = NULL;
+       CFMutableDictionaryRef          newProxy;
+       static const audit_token_t      null_audit      = KERNEL_AUDIT_TOKEN_VALUE;
+       UUID_DEFINE(null_uuid, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+       CFArrayRef                      proxies         = NULL;
+       CFDictionaryRef                 proxy;
+       int                             sc_status       = kSCStatusOK;
+       CFStringRef                     serviceID;
+       CFStringRef                     trimmed         = NULL;
 
        if (!isA_CFDictionary(globalConfiguration)) {
                // if no proxy configuration
@@ -428,6 +506,49 @@ SCNetworkProxiesCopyMatching(CFDictionaryRef       globalConfiguration,
                return proxies;
        }
 
+       // Check for app-layer VPN proxy results (with or without server)
+       serviceID = VPNAppLayerCopyMatchingService(null_audit, 0, null_uuid, NULL, server, NULL, NULL);
+       if (serviceID != NULL) {
+               CFDictionaryRef serviceProxies  = NULL;
+
+               serviceProxies = CFDictionaryGetValue(globalConfiguration, kSCPropNetProxiesServices);
+               if (serviceProxies == NULL) {
+                       _SCErrorSet(kSCStatusOK);
+                       CFRelease(serviceID);
+                       goto app_layer_no_proxies;
+               }
+               if (!isA_CFDictionary(serviceProxies)) {
+                       _SCErrorSet(kSCStatusFailed);
+                       CFRelease(serviceID);
+                       goto app_layer_no_proxies;
+               }
+
+               proxy = CFDictionaryGetValue(serviceProxies, serviceID);
+               CFRelease(serviceID);
+               if (proxy == NULL) {
+                       _SCErrorSet(kSCStatusOK);
+                       goto app_layer_no_proxies;
+               }
+               if (!isA_CFDictionary(proxy)) {
+                       _SCErrorSet(kSCStatusFailed);
+                       goto app_layer_no_proxies;
+               }
+
+               proxies = CFArrayCreate(NULL, (const void **)&proxy, 1, &kCFTypeArrayCallBacks);
+               return proxies;
+
+           app_layer_no_proxies:
+
+               /*
+                * Rather than returning NULL, return an empty proxy configuration.
+                * This ensures that the global proxy configuration will not be used.
+                */
+               proxy = CFDictionaryCreate(NULL, NULL, NULL, 0, NULL, NULL);
+               proxies = CFArrayCreate(NULL, (const void **)&proxy, 1, &kCFTypeArrayCallBacks);
+               CFRelease(proxy);
+               return proxies;
+       }
+
        if (server != NULL) {
                CFIndex                 i;
                CFMutableArrayRef       matching        = NULL;
@@ -523,6 +644,7 @@ SCNetworkProxiesCopyMatching(CFDictionaryRef        globalConfiguration,
 
        newProxy = CFDictionaryCreateMutableCopy(NULL, 0, globalConfiguration);
        CFDictionaryRemoveValue(newProxy, kSCPropNetProxiesScoped);
+       CFDictionaryRemoveValue(newProxy, kSCPropNetProxiesServices);
        CFDictionaryRemoveValue(newProxy, kSCPropNetProxiesSupplemental);
        proxies = CFArrayCreate(NULL, (const void **)&newProxy, 1, &kCFTypeArrayCallBacks);
        CFRelease(newProxy);
index 583307d9f9028110ec5a3ff96ad859ffd3b65e15..4df5ad60997cd5cfbd23dba75e57ee45b85f7e11 100644 (file)
@@ -61,7 +61,9 @@ const CFStringRef kSCEntNetSMB                                     = CFSTR("SMB"
 const CFStringRef kSCEntNet6to4                                    = CFSTR("6to4");
 
 
+const CFStringRef kSCEntNetAppLayer                                = CFSTR("AppLayer");
 const CFStringRef kSCEntNetEAPOL                                   = CFSTR("EAPOL");
+const CFStringRef kSCEntNetLinkIssues                              = CFSTR("LinkIssues");
 const CFStringRef kSCEntNetLinkQuality                             = CFSTR("LinkQuality");
 const CFStringRef kSCEntNetLoopback                                = CFSTR("Loopback");
 const CFStringRef kSCEntNetOnDemand                                = CFSTR("OnDemand");
@@ -114,6 +116,8 @@ const CFStringRef kSCPropNetDNSServerTimeout                       = CFSTR("Serv
 const CFStringRef kSCPropNetDNSSortList                            = CFSTR("SortList");
 const CFStringRef kSCPropNetDNSSupplementalMatchDomains            = CFSTR("SupplementalMatchDomains");
 const CFStringRef kSCPropNetDNSSupplementalMatchOrders             = CFSTR("SupplementalMatchOrders");
+const CFStringRef kSCPropNetDNSServiceIdentifier                   = CFSTR("ServiceIdentifier");
+const CFStringRef kSCPropNetDNSSupplementalMatchDomainsNoSearch    = CFSTR("SupplementalMatchDomainsNoSearch");
 const CFStringRef kSCPropNetEthernetMediaSubType                   = CFSTR("MediaSubType");
 const CFStringRef kSCPropNetEthernetMediaOptions                   = CFSTR("MediaOptions");
 const CFStringRef kSCPropNetEthernetMTU                            = CFSTR("MTU");
@@ -156,6 +160,8 @@ const CFStringRef kSCPropNetIPSecXAuthEnabled                      = CFSTR("XAut
 const CFStringRef kSCPropNetIPSecXAuthName                         = CFSTR("XAuthName");
 const CFStringRef kSCPropNetIPSecXAuthPassword                     = CFSTR("XAuthPassword");
 const CFStringRef kSCPropNetIPSecXAuthPasswordEncryption           = CFSTR("XAuthPasswordEncryption");
+const CFStringRef kSCPropNetIPSecDisconnectOnWake                  = CFSTR("DisconnectOnWake");
+const CFStringRef kSCPropNetIPSecDisconnectOnWakeTimer             = CFSTR("DisconnectOnWakeTimer");
 const CFStringRef kSCValNetIPSecAuthenticationMethodSharedSecret   = CFSTR("SharedSecret");
 const CFStringRef kSCValNetIPSecAuthenticationMethodCertificate    = CFSTR("Certificate");
 const CFStringRef kSCValNetIPSecAuthenticationMethodHybrid         = CFSTR("Hybrid");
@@ -209,6 +215,9 @@ const CFStringRef kSCPropNetIPv6RouteGatewayAddress                = CFSTR("Gate
 const CFStringRef kSCPropNet6to4Relay                              = CFSTR("Relay");
 const CFStringRef kSCPropNetLinkActive                             = CFSTR("Active");
 const CFStringRef kSCPropNetLinkDetaching                          = CFSTR("Detaching");
+const CFStringRef kSCPropNetLinkIssuesModuleID                     = CFSTR("ModuleID");
+const CFStringRef kSCPropNetLinkIssuesInfo                         = CFSTR("Info");
+const CFStringRef kSCPropNetLinkIssuesTimeStamp                    = CFSTR("TimeStamp");
 const CFStringRef kSCPropNetLinkQuality                            = CFSTR("LinkQuality");
 const CFStringRef kSCPropNetModemAccessPointName                   = CFSTR("AccessPointName");
 const CFStringRef kSCPropNetModemConnectionPersonality             = CFSTR("ConnectionPersonality");
@@ -253,6 +262,8 @@ const CFStringRef kSCPropNetPPPDisconnectOnIdle                    = CFSTR("Disc
 const CFStringRef kSCPropNetPPPDisconnectOnIdleTimer               = CFSTR("DisconnectOnIdleTimer");
 const CFStringRef kSCPropNetPPPDisconnectOnLogout                  = CFSTR("DisconnectOnLogout");
 const CFStringRef kSCPropNetPPPDisconnectOnSleep                   = CFSTR("DisconnectOnSleep");
+const CFStringRef kSCPropNetPPPDisconnectOnWake                    = CFSTR("DisconnectOnWake");
+const CFStringRef kSCPropNetPPPDisconnectOnWakeTimer               = CFSTR("DisconnectOnWakeTimer");
 const CFStringRef kSCPropNetPPPDisconnectTime                      = CFSTR("DisconnectTime");
 const CFStringRef kSCPropNetPPPIdleReminderTimer                   = CFSTR("IdleReminderTimer");
 const CFStringRef kSCPropNetPPPIdleReminder                        = CFSTR("IdleReminder");
@@ -347,9 +358,12 @@ const CFStringRef kSCPropNetProxiesProxyAutoConfigEnable           = CFSTR("Prox
 const CFStringRef kSCPropNetProxiesProxyAutoConfigJavaScript       = CFSTR("ProxyAutoConfigJavaScript");
 const CFStringRef kSCPropNetProxiesProxyAutoConfigURLString        = CFSTR("ProxyAutoConfigURLString");
 const CFStringRef kSCPropNetProxiesProxyAutoDiscoveryEnable        = CFSTR("ProxyAutoDiscoveryEnable");
+const CFStringRef kSCPropNetProxiesBypassAllowed                   = CFSTR("BypassAllowed");
+const CFStringRef kSCPropNetProxiesFallBackAllowed                 = CFSTR("FallBackAllowed");
 const CFStringRef kSCPropNetProxiesSupplementalMatchDomains        = CFSTR("SupplementalMatchDomains");
 const CFStringRef kSCPropNetProxiesSupplementalMatchOrders         = CFSTR("SupplementalMatchOrders");
 const CFStringRef kSCPropNetProxiesScoped                          = CFSTR("__SCOPED__");
+const CFStringRef kSCPropNetProxiesServices                        = CFSTR("__SERVICES__");
 const CFStringRef kSCPropNetProxiesSupplemental                    = CFSTR("__SUPPLEMENTAL__");
 const CFStringRef kSCPropNetProxiesSupplementalMatchDomain         = CFSTR("__MATCH_DOMAIN__");
 const CFStringRef kSCPropNetServicePrimaryRank                     = CFSTR("PrimaryRank");
@@ -370,9 +384,12 @@ const CFStringRef kSCValNetSMBNetBIOSNodeTypeMixed                 = CFSTR("Mixe
 const CFStringRef kSCValNetSMBNetBIOSNodeTypeHybrid                = CFSTR("Hybrid");
 #endif // !TARGET_OS_IPHONE
 
+const CFStringRef kSCPropNetVPNAppRules                            = CFSTR("AppRules");
+const CFStringRef kSCPropNetVPNAuthCredentialPassword              = CFSTR("AuthCredentialPassword");
 const CFStringRef kSCPropNetVPNAuthName                            = CFSTR("AuthName");
 const CFStringRef kSCPropNetVPNAuthPassword                        = CFSTR("AuthPassword");
 const CFStringRef kSCPropNetVPNAuthPasswordEncryption              = CFSTR("AuthPasswordEncryption");
+const CFStringRef kSCPropNetVPNAuthPasswordPluginType              = CFSTR("AuthPasswordPluginType");
 const CFStringRef kSCPropNetVPNAuthenticationMethod                = CFSTR("AuthenticationMethod");
 const CFStringRef kSCPropNetVPNConnectTime                         = CFSTR("ConnectTime");
 const CFStringRef kSCPropNetVPNDisconnectOnFastUserSwitch          = CFSTR("DisconnectOnFastUserSwitch");
@@ -380,20 +397,57 @@ const CFStringRef kSCPropNetVPNDisconnectOnIdle                    = CFSTR("Disc
 const CFStringRef kSCPropNetVPNDisconnectOnIdleTimer               = CFSTR("DisconnectOnIdleTimer");
 const CFStringRef kSCPropNetVPNDisconnectOnLogout                  = CFSTR("DisconnectOnLogout");
 const CFStringRef kSCPropNetVPNDisconnectOnSleep                   = CFSTR("DisconnectOnSleep");
+const CFStringRef kSCPropNetVPNDisconnectOnWake                    = CFSTR("DisconnectOnWake");
+const CFStringRef kSCPropNetVPNDisconnectOnWakeTimer               = CFSTR("DisconnectOnWakeTimer");
 const CFStringRef kSCPropNetVPNLocalCertificate                    = CFSTR("LocalCertificate");
 const CFStringRef kSCPropNetVPNLogfile                             = CFSTR("Logfile");
 const CFStringRef kSCPropNetVPNMTU                                 = CFSTR("MTU");
 const CFStringRef kSCPropNetVPNOnDemandEnabled                     = CFSTR("OnDemandEnabled");
+const CFStringRef kSCPropNetVPNOnDemandMatchAppEnabled             = CFSTR("OnDemandMatchAppEnabled");
 const CFStringRef kSCPropNetVPNOnDemandMatchDomainsAlways          = CFSTR("OnDemandMatchDomainsAlways");
 const CFStringRef kSCPropNetVPNOnDemandMatchDomainsOnRetry         = CFSTR("OnDemandMatchDomainsOnRetry");
 const CFStringRef kSCPropNetVPNOnDemandMatchDomainsNever           = CFSTR("OnDemandMatchDomainsNever");
+const CFStringRef kSCPropNetVPNOnDemandRules                       = CFSTR("OnDemandRules");
+const CFStringRef kSCPropNetVPNOnDemandSuspended                   = CFSTR("OnDemandSuspended");
+const CFStringRef kSCPropNetVPNPluginCapability                    = CFSTR("PluginCapability");
 const CFStringRef kSCPropNetVPNRemoteAddress                       = CFSTR("RemoteAddress");
 const CFStringRef kSCPropNetVPNStatus                              = CFSTR("Status");
 const CFStringRef kSCPropNetVPNVerboseLogging                      = CFSTR("VerboseLogging");
+const CFStringRef kSCValNetVPNAppRuleAccountIdentifierMatch        = CFSTR("AccountIdentifierMatch");
+const CFStringRef kSCValNetVPNAppRuleDNSDomainMatch                = CFSTR("DNSDomainMatch");
+const CFStringRef kSCValNetVPNAppRuleExecutableMatch               = CFSTR("ExecutableMatch");
+const CFStringRef kSCValNetVPNAppRuleIdentifier                    = CFSTR("Identifier");
+const CFStringRef kSCValNetVPNAppRuleExecutableDesignatedRequirement = CFSTR("DesignatedRequirement");
+const CFStringRef kSCValNetVPNAppRuleExecutableSigningIdentifier   = CFSTR("SigningIdentifier");
 const CFStringRef kSCValNetVPNAuthenticationMethodPassword         = CFSTR("Password");
 const CFStringRef kSCValNetVPNAuthenticationMethodCertificate      = CFSTR("Certificate");
+const CFStringRef kSCValNetVPNAuthPasswordEncryptionExternal       = CFSTR("External");
 const CFStringRef kSCValNetVPNAuthPasswordEncryptionKeychain       = CFSTR("Keychain");
 const CFStringRef kSCValNetVPNAuthPasswordEncryptionPrompt         = CFSTR("Prompt");
+const CFStringRef kSCPropNetVPNOnDemandRuleAction                  = CFSTR("Action");
+const CFStringRef kSCPropNetVPNOnDemandRuleActionParameters        = CFSTR("ActionParameters");
+const CFStringRef kSCPropNetVPNOnDemandRuleDNSDomainMatch          = CFSTR("DNSDomainMatch");
+const CFStringRef kSCPropNetVPNOnDemandRuleDNSServerAddressMatch   = CFSTR("DNSServerAddressMatch");
+const CFStringRef kSCPropNetVPNOnDemandRuleSSIDMatch               = CFSTR("SSIDMatch");
+const CFStringRef kSCPropNetVPNOnDemandRuleInterfaceTypeMatch      = CFSTR("InterfaceTypeMatch");
+const CFStringRef kSCPropNetVPNOnDemandRuleURLStringProbe          = CFSTR("URLStringProbe");
+const CFStringRef kSCValNetVPNOnDemandRuleActionAllow              = CFSTR("Allow");
+const CFStringRef kSCValNetVPNOnDemandRuleActionIgnore             = CFSTR("Ignore");
+const CFStringRef kSCValNetVPNOnDemandRuleActionConnect            = CFSTR("Connect");
+const CFStringRef kSCValNetVPNOnDemandRuleActionDisconnect         = CFSTR("Disconnect");
+const CFStringRef kSCValNetVPNOnDemandRuleActionEvaluateConnection = CFSTR("EvaluateConnection");
+const CFStringRef kSCPropNetVPNOnDemandRuleActionParametersDomainAction = CFSTR("DomainAction");
+const CFStringRef kSCPropNetVPNOnDemandRuleActionParametersDomains = CFSTR("Domains");
+const CFStringRef kSCPropNetVPNOnDemandRuleActionParametersRequiredDNSServers = CFSTR("RequiredDNSServers");
+const CFStringRef kSCPropNetVPNOnDemandRuleActionParametersRequiredURLStringProbe = CFSTR("RequiredURLStringProbe");
+const CFStringRef kSCValNetVPNOnDemandRuleActionParametersDomainActionConnectIfNeeded = CFSTR("ConnectIfNeeded");
+const CFStringRef kSCValNetVPNOnDemandRuleActionParametersDomainActionNeverConnect = CFSTR("NeverConnect");
+
+
+const CFStringRef kSCValNetVPNOnDemandRuleInterfaceTypeMatchEthernet = CFSTR("Ethernet");
+const CFStringRef kSCValNetVPNOnDemandRuleInterfaceTypeMatchWiFi   = CFSTR("WiFi");
+const CFStringRef kSCValNetVPNPluginCapabilityAuth                 = CFSTR("Auth");
+const CFStringRef kSCValNetVPNPluginCapabilityConnect              = CFSTR("Connect");
 
 #if !TARGET_OS_IPHONE
 const CFStringRef kSCEntUsersConsoleUser                           = CFSTR("ConsoleUser");
index 22e2b0b40c96ed498118dd6da50b9b6617b383e8..af6f711430aaeec37977fd1fc62eabd2e7ab0431 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  *
  *   kSCPropNetLocalHostName                            "LocalHostName"                CFString
  *
- * kSCEntNetAirPort (Hardware) Entity Keys
- *
- *   kSCPropNetAirPortAllowNetCreation                  "AllowNetCreation"             CFNumber (0 or 1)
- *   kSCPropNetAirPortAuthPassword                      "AuthPassword"                 CFData
- *   kSCPropNetAirPortAuthPasswordEncryption            "AuthPasswordEncryption"       CFString
- *   kSCPropNetAirPortJoinMode                          "JoinMode"                     CFString
- *   kSCPropNetAirPortPowerEnabled                      "PowerEnabled"                 CFNumber (0 or 1)
- *   kSCPropNetAirPortPreferredNetwork                  "PreferredNetwork"             CFString
- *   kSCPropNetAirPortSavePasswords                     "SavePasswords"                CFNumber (0 or 1)
- *
- *   --- kSCPropNetAirPortJoinMode values ---
- *   kSCValNetAirPortJoinModeAutomatic                  "Automatic"
- *   kSCValNetAirPortJoinModePreferred                  "Preferred"
- *   kSCValNetAirPortJoinModeRanked                     "Ranked"
- *   kSCValNetAirPortJoinModeRecent                     "Recent"
- *   kSCValNetAirPortJoinModeStrongest                  "Strongest"
- *
- *   --- kSCPropNetAirPortPasswordEncryption values ---
- *   kSCValNetAirPortAuthPasswordEncryptionKeychain     "Keychain"
- *
  * kSCEntNetDNS Entity Keys
  *
  *   kSCPropNetDNSDomainName                            "DomainName"                   CFString
@@ -806,79 +786,79 @@ extern const CFStringRef kSCPropNetLocalHostName;
 
 /*!
   @const kSCPropNetAirPortAllowNetCreation
-  @availability Introduced in Mac OS X 10.2.
+  @availability Introduced in Mac OS X 10.2, but later deprecated in Mac OS X 10.9.
  */
 extern const CFStringRef kSCPropNetAirPortAllowNetCreation;
 
 /*!
   @const kSCPropNetAirPortAuthPassword
-  @availability Introduced in Mac OS X 10.1.
+  @availability Introduced in Mac OS X 10.1, but later deprecated in Mac OS X 10.9.
  */
 extern const CFStringRef kSCPropNetAirPortAuthPassword;
 
 /*!
   @const kSCPropNetAirPortAuthPasswordEncryption
-  @availability Introduced in Mac OS X 10.1.
+  @availability Introduced in Mac OS X 10.1, but later deprecated in Mac OS X 10.9.
  */
 extern const CFStringRef kSCPropNetAirPortAuthPasswordEncryption;
 
 /*!
   @const kSCPropNetAirPortJoinMode
-  @availability Introduced in Mac OS X 10.2.
+  @availability Introduced in Mac OS X 10.2, but later deprecated in Mac OS X 10.9.
  */
 extern const CFStringRef kSCPropNetAirPortJoinMode;
 
 /*!
   @const kSCPropNetAirPortPowerEnabled
-  @availability Introduced in Mac OS X 10.1.
+  @availability Introduced in Mac OS X 10.1, but later deprecated in Mac OS X 10.9.
  */
 extern const CFStringRef kSCPropNetAirPortPowerEnabled;
 
 /*!
   @const kSCPropNetAirPortPreferredNetwork
-  @availability Introduced in Mac OS X 10.1.
+  @availability Introduced in Mac OS X 10.1, but later deprecated in Mac OS X 10.9.
  */
 extern const CFStringRef kSCPropNetAirPortPreferredNetwork;
 
 /*!
   @const kSCPropNetAirPortSavePasswords
-  @availability Introduced in Mac OS X 10.2.
+  @availability Introduced in Mac OS X 10.2, but later deprecated in Mac OS X 10.9.
  */
 extern const CFStringRef kSCPropNetAirPortSavePasswords;
 
 /*!
   @const kSCValNetAirPortJoinModeAutomatic
-  @availability Introduced in Mac OS X 10.3.
+  @availability Introduced in Mac OS X 10.3, but later deprecated in Mac OS X 10.9.
  */
 extern const CFStringRef kSCValNetAirPortJoinModeAutomatic;
 
 /*!
   @const kSCValNetAirPortJoinModePreferred
-  @availability Introduced in Mac OS X 10.2.
+  @availability Introduced in Mac OS X 10.2, but later deprecated in Mac OS X 10.9.
  */
 extern const CFStringRef kSCValNetAirPortJoinModePreferred;
 
 /*!
   @const kSCValNetAirPortJoinModeRanked
-  @availability Introduced in Mac OS X 10.4.
+  @availability Introduced in Mac OS X 10.4, but later deprecated in Mac OS X 10.9.
  */
 extern const CFStringRef kSCValNetAirPortJoinModeRanked;
 
 /*!
   @const kSCValNetAirPortJoinModeRecent
-  @availability Introduced in Mac OS X 10.2.
+  @availability Introduced in Mac OS X 10.2, but later deprecated in Mac OS X 10.9.
  */
 extern const CFStringRef kSCValNetAirPortJoinModeRecent;
 
 /*!
   @const kSCValNetAirPortJoinModeStrongest
-  @availability Introduced in Mac OS X 10.2.
+  @availability Introduced in Mac OS X 10.2, but later deprecated in Mac OS X 10.9.
  */
 extern const CFStringRef kSCValNetAirPortJoinModeStrongest;
 
 /*!
   @const kSCValNetAirPortAuthPasswordEncryptionKeychain
-  @availability Introduced in Mac OS X 10.3.
+  @availability Introduced in Mac OS X 10.3, but later deprecated in Mac OS X 10.9.
  */
 extern const CFStringRef kSCValNetAirPortAuthPasswordEncryptionKeychain;
 
@@ -2375,6 +2355,7 @@ extern const CFStringRef kSCPropUsersConsoleUserGID;
 
 /* -------------------- Schema declarations -------------------- */
 
+#define        __AVAILABILITY_INTERNAL__IPHONE_2_0_DEP__IPHONE_FUTURE  __AVAILABILITY_INTERNAL__IPHONE_2_0/*SPI*/
 
   SC_SCHEMA_DECLARATION(kSCResvLink, __OSX_AVAILABLE_STARTING(__MAC_10_1,__IPHONE_2_0/*SPI*/))
   #define kSCResvLink                                                   \
@@ -2652,79 +2633,79 @@ extern const CFStringRef kSCPropUsersConsoleUserGID;
                      ,"LocalHostName"                                  \
                      ,CFString                                         )
 
-  SC_SCHEMA_DECLARATION(kSCPropNetAirPortAllowNetCreation, __OSX_AVAILABLE_STARTING(__MAC_10_2,__IPHONE_2_0/*SPI*/))
+  SC_SCHEMA_DECLARATION(kSCPropNetAirPortAllowNetCreation, __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2,__MAC_10_9,__IPHONE_2_0/*SPI*/,__IPHONE_FUTURE/*SPI*/))
   #define kSCPropNetAirPortAllowNetCreation                             \
          SC_SCHEMA_KV(kSCPropNetAirPortAllowNetCreation                \
                      ,"AllowNetCreation"                               \
                      ,CFNumber (0 or 1)                                )
 
-  SC_SCHEMA_DECLARATION(kSCPropNetAirPortAuthPassword, __OSX_AVAILABLE_STARTING(__MAC_10_1,__IPHONE_2_0/*SPI*/))
+  SC_SCHEMA_DECLARATION(kSCPropNetAirPortAuthPassword, __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_1,__MAC_10_9,__IPHONE_2_0/*SPI*/,__IPHONE_FUTURE/*SPI*/))
   #define kSCPropNetAirPortAuthPassword                                 \
          SC_SCHEMA_KV(kSCPropNetAirPortAuthPassword                    \
                      ,"AuthPassword"                                   \
                      ,CFData                                           )
 
-  SC_SCHEMA_DECLARATION(kSCPropNetAirPortAuthPasswordEncryption, __OSX_AVAILABLE_STARTING(__MAC_10_1,__IPHONE_2_0/*SPI*/))
+  SC_SCHEMA_DECLARATION(kSCPropNetAirPortAuthPasswordEncryption, __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_1,__MAC_10_9,__IPHONE_2_0/*SPI*/,__IPHONE_FUTURE/*SPI*/))
   #define kSCPropNetAirPortAuthPasswordEncryption                       \
          SC_SCHEMA_KV(kSCPropNetAirPortAuthPasswordEncryption          \
                      ,"AuthPasswordEncryption"                         \
                      ,CFString                                         )
 
-  SC_SCHEMA_DECLARATION(kSCPropNetAirPortJoinMode, __OSX_AVAILABLE_STARTING(__MAC_10_2,__IPHONE_2_0/*SPI*/))
+  SC_SCHEMA_DECLARATION(kSCPropNetAirPortJoinMode, __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2,__MAC_10_9,__IPHONE_2_0/*SPI*/,__IPHONE_FUTURE/*SPI*/))
   #define kSCPropNetAirPortJoinMode                                     \
          SC_SCHEMA_KV(kSCPropNetAirPortJoinMode                        \
                      ,"JoinMode"                                       \
                      ,CFString                                         )
 
-  SC_SCHEMA_DECLARATION(kSCPropNetAirPortPowerEnabled, __OSX_AVAILABLE_STARTING(__MAC_10_1,__IPHONE_2_0/*SPI*/))
+  SC_SCHEMA_DECLARATION(kSCPropNetAirPortPowerEnabled, __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_1,__MAC_10_9,__IPHONE_2_0/*SPI*/,__IPHONE_FUTURE/*SPI*/))
   #define kSCPropNetAirPortPowerEnabled                                 \
          SC_SCHEMA_KV(kSCPropNetAirPortPowerEnabled                    \
                      ,"PowerEnabled"                                   \
                      ,CFNumber (0 or 1)                                )
 
-  SC_SCHEMA_DECLARATION(kSCPropNetAirPortPreferredNetwork, __OSX_AVAILABLE_STARTING(__MAC_10_1,__IPHONE_2_0/*SPI*/))
+  SC_SCHEMA_DECLARATION(kSCPropNetAirPortPreferredNetwork, __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_1,__MAC_10_9,__IPHONE_2_0/*SPI*/,__IPHONE_FUTURE/*SPI*/))
   #define kSCPropNetAirPortPreferredNetwork                             \
          SC_SCHEMA_KV(kSCPropNetAirPortPreferredNetwork                \
                      ,"PreferredNetwork"                               \
                      ,CFString                                         )
 
-  SC_SCHEMA_DECLARATION(kSCPropNetAirPortSavePasswords, __OSX_AVAILABLE_STARTING(__MAC_10_2,__IPHONE_2_0/*SPI*/))
+  SC_SCHEMA_DECLARATION(kSCPropNetAirPortSavePasswords, __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2,__MAC_10_9,__IPHONE_2_0/*SPI*/,__IPHONE_FUTURE/*SPI*/))
   #define kSCPropNetAirPortSavePasswords                                \
          SC_SCHEMA_KV(kSCPropNetAirPortSavePasswords                   \
                      ,"SavePasswords"                                  \
                      ,CFNumber (0 or 1)                                )
 
-  SC_SCHEMA_DECLARATION(kSCValNetAirPortJoinModeAutomatic, __OSX_AVAILABLE_STARTING(__MAC_10_3,__IPHONE_2_0/*SPI*/))
+  SC_SCHEMA_DECLARATION(kSCValNetAirPortJoinModeAutomatic, __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_3,__MAC_10_9,__IPHONE_2_0/*SPI*/,__IPHONE_FUTURE/*SPI*/))
   #define kSCValNetAirPortJoinModeAutomatic                             \
          SC_SCHEMA_KV(kSCValNetAirPortJoinModeAutomatic                \
                      ,"Automatic"                                      \
                      ,                                                 )
 
-  SC_SCHEMA_DECLARATION(kSCValNetAirPortJoinModePreferred, __OSX_AVAILABLE_STARTING(__MAC_10_2,__IPHONE_2_0/*SPI*/))
+  SC_SCHEMA_DECLARATION(kSCValNetAirPortJoinModePreferred, __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2,__MAC_10_9,__IPHONE_2_0/*SPI*/,__IPHONE_FUTURE/*SPI*/))
   #define kSCValNetAirPortJoinModePreferred                             \
          SC_SCHEMA_KV(kSCValNetAirPortJoinModePreferred                \
                      ,"Preferred"                                      \
                      ,                                                 )
 
-  SC_SCHEMA_DECLARATION(kSCValNetAirPortJoinModeRanked, __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0/*SPI*/))
+  SC_SCHEMA_DECLARATION(kSCValNetAirPortJoinModeRanked, __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4,__MAC_10_9,__IPHONE_2_0/*SPI*/,__IPHONE_FUTURE/*SPI*/))
   #define kSCValNetAirPortJoinModeRanked                                \
          SC_SCHEMA_KV(kSCValNetAirPortJoinModeRanked                   \
                      ,"Ranked"                                         \
                      ,                                                 )
 
-  SC_SCHEMA_DECLARATION(kSCValNetAirPortJoinModeRecent, __OSX_AVAILABLE_STARTING(__MAC_10_2,__IPHONE_2_0/*SPI*/))
+  SC_SCHEMA_DECLARATION(kSCValNetAirPortJoinModeRecent, __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2,__MAC_10_9,__IPHONE_2_0/*SPI*/,__IPHONE_FUTURE/*SPI*/))
   #define kSCValNetAirPortJoinModeRecent                                \
          SC_SCHEMA_KV(kSCValNetAirPortJoinModeRecent                   \
                      ,"Recent"                                         \
                      ,                                                 )
 
-  SC_SCHEMA_DECLARATION(kSCValNetAirPortJoinModeStrongest, __OSX_AVAILABLE_STARTING(__MAC_10_2,__IPHONE_2_0/*SPI*/))
+  SC_SCHEMA_DECLARATION(kSCValNetAirPortJoinModeStrongest, __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2,__MAC_10_9,__IPHONE_2_0/*SPI*/,__IPHONE_FUTURE/*SPI*/))
   #define kSCValNetAirPortJoinModeStrongest                             \
          SC_SCHEMA_KV(kSCValNetAirPortJoinModeStrongest                \
                      ,"Strongest"                                      \
                      ,                                                 )
 
-  SC_SCHEMA_DECLARATION(kSCValNetAirPortAuthPasswordEncryptionKeychain, __OSX_AVAILABLE_STARTING(__MAC_10_3,__IPHONE_2_0/*SPI*/))
+  SC_SCHEMA_DECLARATION(kSCValNetAirPortAuthPasswordEncryptionKeychain, __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_3,__MAC_10_9,__IPHONE_2_0/*SPI*/,__IPHONE_FUTURE/*SPI*/))
   #define kSCValNetAirPortAuthPasswordEncryptionKeychain                \
          SC_SCHEMA_KV(kSCValNetAirPortAuthPasswordEncryptionKeychain   \
                      ,"Keychain"                                       \
index ee3ca283b59f6c06d51b52b3950b3baeb665f7eb..509be002d5f80cb92050cca00960eba19e682be3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -34,7 +34,9 @@
  * Network Entity Keys
  *
  *   kSCEntNetCommCenter                                "com.apple.CommCenter"         CFDictionary
+ *   kSCEntNetAppLayer                                  "AppLayer"                     CFDictionary
  *   kSCEntNetEAPOL                                     "EAPOL"                        CFDictionary
+ *   kSCEntNetLinkIssues                                "LinkIssues"                   CFDictionary
  *   kSCEntNetLinkQuality                               "LinkQuality"                  CFDictionary
  *   kSCEntNetLoopback                                  "Loopback"                     CFDictionary
  *   kSCEntNetOnDemand                                  "OnDemand"                     CFDictionary
  *   kSCPropNetCommCenterAllowNetworkAccess             "AllowNetworkAccess"           CFNumber (0 or 1)
  *   kSCPropNetCommCenterAvailable                      "Available"                    CFNumber (0 or 1)
  *
+ * kSCEntNetDNS Entity Keys
+ *
+ *   kSCPropNetDNSServiceIdentifier                     "ServiceIdentifier"            CFNumber
+ *   kSCPropNetDNSSupplementalMatchDomainsNoSearch      "SupplementalMatchDomainsNoSearch" CFNumber (0 or 1)
+ *
  * kSCEntNetEthernet (Hardware) Entity Keys
  *
  *   kSCPropNetEthernetCapabilityAV                     "AV"                           CFNumber (0 or 1)
@@ -69,6 +76,8 @@
  *   kSCValNetInterfaceTypeLoopback                     "Loopback"
  *   kSCValNetInterfaceTypeVPN                          "VPN"
  *
+ *   kSCPropNetIPSecDisconnectOnWake                    "DisconnectOnWake"             CFNumber (0 or 1)
+ *   kSCPropNetIPSecDisconnectOnWakeTimer               "DisconnectOnWakeTimer"        CFNumber
  * kSCEntNetIPSec Entity Keys
  *
  *   kSCPropNetIPSecLastCause                           "LastCause"                    CFNumber
  *   kSCPropNetIPv6RoutePrefixLength                    "PrefixLength"                 CFNumber
  *   kSCPropNetIPv6RouteGatewayAddress                  "GatewayAddress"               CFString
  *
+ * kSCEntNetLinkIssues Entity Keys
+ *
+ *   kSCPropNetLinkIssuesModuleID                       "ModuleID"                     CFData
+ *   kSCPropNetLinkIssuesInfo                           "Info"                         CFData
+ *   kSCPropNetLinkIssuesTimeStamp                      "TimeStamp"                    CFDATE
+ *
  * kSCEntNetLinkQuality Entity Keys
  *
  *   kSCPropNetLinkQuality                              "LinkQuality"                  CFNumber
  *
+ *   kSCPropNetPPPDisconnectOnWake                      "DisconnectOnWake"             CFNumber (0 or 1)
+ *   kSCPropNetPPPDisconnectOnWakeTimer                 "DisconnectOnWakeTimer"        CFNumber
  * kSCEntNetPPP Entity Keys
  *
  *   --- OnDemand: ---
  *
  * kSCEntNetProxies Entity Keys
  *
+ *   kSCPropNetProxiesBypassAllowed                     "BypassAllowed"                CFNumber (0 or 1)
+ *   kSCPropNetProxiesFallBackAllowed                   "FallBackAllowed"              CFNumber (0 or 1)
  *   kSCPropNetProxiesSupplementalMatchDomains          "SupplementalMatchDomains"     CFArray[CFString]
  *   kSCPropNetProxiesSupplementalMatchOrders           "SupplementalMatchOrders"      CFArray[CFNumber]
  *
  *   kSCPropNetProxiesScoped                            "__SCOPED__"                   CFDictionary
+ *   kSCPropNetProxiesServices                          "__SERVICES__"                 CFDictionary
  *   kSCPropNetProxiesSupplemental                      "__SUPPLEMENTAL__"             CFArray[CFDictionary]
  *   kSCPropNetProxiesSupplementalMatchDomain           "__MATCH_DOMAIN__"             CFString
  *
  *
  * kSCEntNetVPN Entity Keys
  *
+ *   kSCPropNetVPNAppRules                              "AppRules"                     CFArray[CFDictionary]
+ *   kSCPropNetVPNAuthCredentialPassword                "AuthCredentialPassword"       CFString
  *   kSCPropNetVPNAuthName                              "AuthName"                     CFString
  *   kSCPropNetVPNAuthPassword                          "AuthPassword"                 CFString
  *   kSCPropNetVPNAuthPasswordEncryption                "AuthPasswordEncryption"       CFString
+ *   kSCPropNetVPNAuthPasswordPluginType                "AuthPasswordPluginType"       CFString
  *   kSCPropNetVPNAuthenticationMethod                  "AuthenticationMethod"         CFString
  *   kSCPropNetVPNConnectTime                           "ConnectTime"                  CFString
  *   kSCPropNetVPNDisconnectOnFastUserSwitch            "DisconnectOnFastUserSwitch"   CFNumber (0 or 1)
  *   kSCPropNetVPNDisconnectOnIdleTimer                 "DisconnectOnIdleTimer"        CFNumber
  *   kSCPropNetVPNDisconnectOnLogout                    "DisconnectOnLogout"           CFNumber (0 or 1)
  *   kSCPropNetVPNDisconnectOnSleep                     "DisconnectOnSleep"            CFNumber (0 or 1)
+ *   kSCPropNetVPNDisconnectOnWake                      "DisconnectOnWake"             CFNumber (0 or 1)
+ *   kSCPropNetVPNDisconnectOnWakeTimer                 "DisconnectOnWakeTimer"        CFNumber
  *   kSCPropNetVPNLocalCertificate                      "LocalCertificate"             CFData
  *   kSCPropNetVPNLogfile                               "Logfile"                      CFString
  *   kSCPropNetVPNMTU                                   "MTU"                          CFNumber
  *   kSCPropNetVPNOnDemandEnabled                       "OnDemandEnabled"              CFNumber (0 or 1)
+ *   kSCPropNetVPNOnDemandMatchAppEnabled               "OnDemandMatchAppEnabled"      CFBoolean
  *   kSCPropNetVPNOnDemandMatchDomainsAlways            "OnDemandMatchDomainsAlways"   CFArray[CFString]
  *   kSCPropNetVPNOnDemandMatchDomainsOnRetry           "OnDemandMatchDomainsOnRetry"  CFArray[CFString]
  *   kSCPropNetVPNOnDemandMatchDomainsNever             "OnDemandMatchDomainsNever"    CFArray[CFString]
+ *   kSCPropNetVPNOnDemandRules                         "OnDemandRules"                CFArray[CFDictionary]
+ *   kSCPropNetVPNOnDemandSuspended                     "OnDemandSuspended"            CFNumber
+ *   kSCPropNetVPNPluginCapability                      "PluginCapability"             CFString
  *   kSCPropNetVPNRemoteAddress                         "RemoteAddress"                CFString
  *   kSCPropNetVPNStatus                                "Status"                       CFNumber
  *   kSCPropNetVPNVerboseLogging                        "VerboseLogging"               CFNumber (0 or 1)
  *
+ *   --- kSCPropNetVPNAppRules [CFDictionary] keys ---
+ *   kSCValNetVPNAppRuleAccountIdentifierMatch          "AccountIdentifierMatch"       CFArray[CFString]
+ *   kSCValNetVPNAppRuleDNSDomainMatch                  "DNSDomainMatch"               CFArray[CFString]
+ *   kSCValNetVPNAppRuleExecutableMatch                 "ExecutableMatch"              CFArray[CFDictionary]
+ *   kSCValNetVPNAppRuleIdentifier                      "Identifier"                   CFString
+ *
+ *   --- kSCValNetVPNAppRuleExecutableMatch [CFDictionary] keys ---
+ *   kSCValNetVPNAppRuleExecutableDesignatedRequirement "DesignatedRequirement"        CFString
+ *   kSCValNetVPNAppRuleExecutableSigningIdentifier     "SigningIdentifier"            CFString
+ *
  *   --- kSCPropNetVPNAuthenticationMethod values ---
  *   kSCValNetVPNAuthenticationMethodPassword           "Password"
  *   kSCValNetVPNAuthenticationMethodCertificate        "Certificate"
  *
  *   --- kSCPropNetVPNAuthPasswordEncryption values ---
+ *   kSCValNetVPNAuthPasswordEncryptionExternal         "External"
  *   kSCValNetVPNAuthPasswordEncryptionKeychain         "Keychain"
  *   kSCValNetVPNAuthPasswordEncryptionPrompt           "Prompt"
  *
+ *   --- kSCPropNetVPNOnDemandRules [CFDictionary] keys ---
+ *   kSCPropNetVPNOnDemandRuleAction                    "Action"                       CFString
+ *   kSCPropNetVPNOnDemandRuleActionParameters          "ActionParameters"             CFArray[CFDictionary]
+ *   kSCPropNetVPNOnDemandRuleDNSDomainMatch            "DNSDomainMatch"               CFArray[CFString]
+ *   kSCPropNetVPNOnDemandRuleDNSServerAddressMatch     "DNSServerAddressMatch"        CFArray[CFString]
+ *   kSCPropNetVPNOnDemandRuleSSIDMatch                 "SSIDMatch"                    CFArray[CFString]
+ *   kSCPropNetVPNOnDemandRuleInterfaceTypeMatch        "InterfaceTypeMatch"           CFString
+ *   kSCPropNetVPNOnDemandRuleURLStringProbe            "URLStringProbe"               CFString
+ *
+ *   --- kSCPropNetVPNOnDemandRuleAction values ---
+ *   kSCValNetVPNOnDemandRuleActionAllow                "Allow"
+ *   kSCValNetVPNOnDemandRuleActionIgnore               "Ignore"
+ *   kSCValNetVPNOnDemandRuleActionConnect              "Connect"
+ *   kSCValNetVPNOnDemandRuleActionDisconnect           "Disconnect"
+ *   kSCValNetVPNOnDemandRuleActionEvaluateConnection   "EvaluateConnection"
+ *
+ *   --- kSCPropNetVPNOnDemandRuleActionParameters [CFDictionary] keys ---
+ *   kSCPropNetVPNOnDemandRuleActionParametersDomainAction "DomainAction"                 CFString
+ *   kSCPropNetVPNOnDemandRuleActionParametersDomains   "Domains"                      CFArray[CFString]
+ *   kSCPropNetVPNOnDemandRuleActionParametersRequiredDNSServers "RequiredDNSServers"           CFArray[CFString]
+ *   kSCPropNetVPNOnDemandRuleActionParametersRequiredURLStringProbe "RequiredURLStringProbe"       CFString
+ *
+ *   --- kSCPropNetVPNOnDemandRuleActionParametersDomainAction values ---
+ *   kSCValNetVPNOnDemandRuleActionParametersDomainActionConnectIfNeeded "ConnectIfNeeded"
+ *   kSCValNetVPNOnDemandRuleActionParametersDomainActionNeverConnect "NeverConnect"
+ *
+ *   --- kSCPropNetVPNOnDemandRuleInterfaceTypeMatch values ---
+ *   kSCValNetVPNOnDemandRuleInterfaceTypeMatchCellular "Cellular"
+ *   kSCValNetVPNOnDemandRuleInterfaceTypeMatchEthernet "Ethernet"
+ *   kSCValNetVPNOnDemandRuleInterfaceTypeMatchWiFi     "WiFi"
+ *
+ *   --- kSCPropNetVPNPluginCapability values ---
+ *   kSCValNetVPNPluginCapabilityAuth                   "Auth"
+ *   kSCValNetVPNPluginCapabilityConnect                "Connect"
+ *
  * kSCCompSystem Properties
  *
  *   kSCPropSystemComputerNameRegion                    "ComputerNameRegion"           CFNumber
@@ -236,12 +311,24 @@ extern const CFStringRef kSCPrefVirtualNetworkInterfaces;
  */
 extern const CFStringRef kSCEntNetCommCenter;
 
+/*!
+  @const kSCEntNetAppLayer
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCEntNetAppLayer;
+
 /*!
   @const kSCEntNetEAPOL
   @availability Introduced in Mac OS X 10.5.
  */
 extern const CFStringRef kSCEntNetEAPOL;
 
+/*!
+  @const kSCEntNetLinkIssues
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCEntNetLinkIssues;
+
 /*!
   @const kSCEntNetLinkQuality
   @availability Introduced in Mac OS X 10.7.
@@ -298,6 +385,22 @@ extern const CFStringRef kSCPropNetCommCenterAllowNetworkAccess;
  */
 extern const CFStringRef kSCPropNetCommCenterAvailable;
 
+/*!
+  @group kSCEntNetDNS Entity Keys
+ */
+
+/*!
+  @const kSCPropNetDNSServiceIdentifier
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCPropNetDNSServiceIdentifier;
+
+/*!
+  @const kSCPropNetDNSSupplementalMatchDomainsNoSearch
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCPropNetDNSSupplementalMatchDomainsNoSearch;
+
 /*!
   @group kSCEntNetEthernet (Hardware) Entity Keys
  */
@@ -378,6 +481,18 @@ extern const CFStringRef kSCValNetInterfaceTypeLoopback;
  */
 extern const CFStringRef kSCValNetInterfaceTypeVPN;
 
+/*!
+  @const kSCPropNetIPSecDisconnectOnWake
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCPropNetIPSecDisconnectOnWake;
+
+/*!
+  @const kSCPropNetIPSecDisconnectOnWakeTimer
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCPropNetIPSecDisconnectOnWakeTimer;
+
 /*!
   @group kSCEntNetIPSec Entity Keys
  */
@@ -498,6 +613,28 @@ extern const CFStringRef kSCPropNetIPv6RoutePrefixLength;
  */
 extern const CFStringRef kSCPropNetIPv6RouteGatewayAddress;
 
+/*!
+  @group kSCEntNetLinkIssues Entity Keys
+ */
+
+/*!
+  @const kSCPropNetLinkIssuesModuleID
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCPropNetLinkIssuesModuleID;
+
+/*!
+  @const kSCPropNetLinkIssuesInfo
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCPropNetLinkIssuesInfo;
+
+/*!
+  @const kSCPropNetLinkIssuesTimeStamp
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCPropNetLinkIssuesTimeStamp;
+
 /*!
   @group kSCEntNetLinkQuality Entity Keys
  */
@@ -508,6 +645,18 @@ extern const CFStringRef kSCPropNetIPv6RouteGatewayAddress;
  */
 extern const CFStringRef kSCPropNetLinkQuality;
 
+/*!
+  @const kSCPropNetPPPDisconnectOnWake
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCPropNetPPPDisconnectOnWake;
+
+/*!
+  @const kSCPropNetPPPDisconnectOnWakeTimer
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCPropNetPPPDisconnectOnWakeTimer;
+
 /*!
   @group kSCEntNetPPP Entity Keys
  */
@@ -600,6 +749,18 @@ extern const CFStringRef kSCValNetPPPOnDemandPriorityLow;
   @group kSCEntNetProxies Entity Keys
  */
 
+/*!
+  @const kSCPropNetProxiesBypassAllowed
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCPropNetProxiesBypassAllowed;
+
+/*!
+  @const kSCPropNetProxiesFallBackAllowed
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCPropNetProxiesFallBackAllowed;
+
 /*!
   @const kSCPropNetProxiesSupplementalMatchDomains
   @availability Introduced in Mac OS X 10.7.
@@ -618,6 +779,12 @@ extern const CFStringRef kSCPropNetProxiesSupplementalMatchOrders;
  */
 extern const CFStringRef kSCPropNetProxiesScoped;
 
+/*!
+  @const kSCPropNetProxiesServices
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCPropNetProxiesServices;
+
 /*!
   @const kSCPropNetProxiesSupplemental
   @availability Introduced in Mac OS X 10.7.
@@ -668,6 +835,18 @@ extern const CFStringRef kSCValNetServicePrimaryRankNever;
   @group kSCEntNetVPN Entity Keys
  */
 
+/*!
+  @const kSCPropNetVPNAppRules
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCPropNetVPNAppRules;
+
+/*!
+  @const kSCPropNetVPNAuthCredentialPassword
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCPropNetVPNAuthCredentialPassword;
+
 /*!
   @const kSCPropNetVPNAuthName
   @availability Introduced in Mac OS X 10.7.
@@ -686,6 +865,12 @@ extern const CFStringRef kSCPropNetVPNAuthPassword;
  */
 extern const CFStringRef kSCPropNetVPNAuthPasswordEncryption;
 
+/*!
+  @const kSCPropNetVPNAuthPasswordPluginType
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCPropNetVPNAuthPasswordPluginType;
+
 /*!
   @const kSCPropNetVPNAuthenticationMethod
   @availability Introduced in Mac OS X 10.7.
@@ -728,6 +913,18 @@ extern const CFStringRef kSCPropNetVPNDisconnectOnLogout;
  */
 extern const CFStringRef kSCPropNetVPNDisconnectOnSleep;
 
+/*!
+  @const kSCPropNetVPNDisconnectOnWake
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCPropNetVPNDisconnectOnWake;
+
+/*!
+  @const kSCPropNetVPNDisconnectOnWakeTimer
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCPropNetVPNDisconnectOnWakeTimer;
+
 /*!
   @const kSCPropNetVPNLocalCertificate
   @availability Introduced in Mac OS X 10.7.
@@ -752,6 +949,12 @@ extern const CFStringRef kSCPropNetVPNMTU;
  */
 extern const CFStringRef kSCPropNetVPNOnDemandEnabled;
 
+/*!
+  @const kSCPropNetVPNOnDemandMatchAppEnabled
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCPropNetVPNOnDemandMatchAppEnabled;
+
 /*!
   @const kSCPropNetVPNOnDemandMatchDomainsAlways
   @availability Introduced in Mac OS X 10.7.
@@ -770,6 +973,24 @@ extern const CFStringRef kSCPropNetVPNOnDemandMatchDomainsOnRetry;
  */
 extern const CFStringRef kSCPropNetVPNOnDemandMatchDomainsNever;
 
+/*!
+  @const kSCPropNetVPNOnDemandRules
+  @availability Introduced in Mac OS X 10.8.
+ */
+extern const CFStringRef kSCPropNetVPNOnDemandRules;
+
+/*!
+  @const kSCPropNetVPNOnDemandSuspended
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCPropNetVPNOnDemandSuspended;
+
+/*!
+  @const kSCPropNetVPNPluginCapability
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCPropNetVPNPluginCapability;
+
 /*!
   @const kSCPropNetVPNRemoteAddress
   @availability Introduced in Mac OS X 10.7.
@@ -788,6 +1009,42 @@ extern const CFStringRef kSCPropNetVPNStatus;
  */
 extern const CFStringRef kSCPropNetVPNVerboseLogging;
 
+/*!
+  @const kSCValNetVPNAppRuleAccountIdentifierMatch
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCValNetVPNAppRuleAccountIdentifierMatch;
+
+/*!
+  @const kSCValNetVPNAppRuleDNSDomainMatch
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCValNetVPNAppRuleDNSDomainMatch;
+
+/*!
+  @const kSCValNetVPNAppRuleExecutableMatch
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCValNetVPNAppRuleExecutableMatch;
+
+/*!
+  @const kSCValNetVPNAppRuleIdentifier
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCValNetVPNAppRuleIdentifier;
+
+/*!
+  @const kSCValNetVPNAppRuleExecutableDesignatedRequirement
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCValNetVPNAppRuleExecutableDesignatedRequirement;
+
+/*!
+  @const kSCValNetVPNAppRuleExecutableSigningIdentifier
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCValNetVPNAppRuleExecutableSigningIdentifier;
+
 /*!
   @const kSCValNetVPNAuthenticationMethodPassword
   @availability Introduced in Mac OS X 10.7.
@@ -800,6 +1057,12 @@ extern const CFStringRef kSCValNetVPNAuthenticationMethodPassword;
  */
 extern const CFStringRef kSCValNetVPNAuthenticationMethodCertificate;
 
+/*!
+  @const kSCValNetVPNAuthPasswordEncryptionExternal
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCValNetVPNAuthPasswordEncryptionExternal;
+
 /*!
   @const kSCValNetVPNAuthPasswordEncryptionKeychain
   @availability Introduced in Mac OS X 10.7.
@@ -812,6 +1075,144 @@ extern const CFStringRef kSCValNetVPNAuthPasswordEncryptionKeychain;
  */
 extern const CFStringRef kSCValNetVPNAuthPasswordEncryptionPrompt;
 
+/*!
+  @const kSCPropNetVPNOnDemandRuleAction
+  @availability Introduced in Mac OS X 10.8.
+ */
+extern const CFStringRef kSCPropNetVPNOnDemandRuleAction;
+
+/*!
+  @const kSCPropNetVPNOnDemandRuleActionParameters
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCPropNetVPNOnDemandRuleActionParameters;
+
+/*!
+  @const kSCPropNetVPNOnDemandRuleDNSDomainMatch
+  @availability Introduced in Mac OS X 10.8.
+ */
+extern const CFStringRef kSCPropNetVPNOnDemandRuleDNSDomainMatch;
+
+/*!
+  @const kSCPropNetVPNOnDemandRuleDNSServerAddressMatch
+  @availability Introduced in Mac OS X 10.8.
+ */
+extern const CFStringRef kSCPropNetVPNOnDemandRuleDNSServerAddressMatch;
+
+/*!
+  @const kSCPropNetVPNOnDemandRuleSSIDMatch
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCPropNetVPNOnDemandRuleSSIDMatch;
+
+/*!
+  @const kSCPropNetVPNOnDemandRuleInterfaceTypeMatch
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCPropNetVPNOnDemandRuleInterfaceTypeMatch;
+
+/*!
+  @const kSCPropNetVPNOnDemandRuleURLStringProbe
+  @availability Introduced in Mac OS X 10.8.
+ */
+extern const CFStringRef kSCPropNetVPNOnDemandRuleURLStringProbe;
+
+/*!
+  @const kSCValNetVPNOnDemandRuleActionAllow
+  @availability Introduced in Mac OS X 10.8.
+ */
+extern const CFStringRef kSCValNetVPNOnDemandRuleActionAllow;
+
+/*!
+  @const kSCValNetVPNOnDemandRuleActionIgnore
+  @availability Introduced in Mac OS X 10.8.
+ */
+extern const CFStringRef kSCValNetVPNOnDemandRuleActionIgnore;
+
+/*!
+  @const kSCValNetVPNOnDemandRuleActionConnect
+  @availability Introduced in Mac OS X 10.8.
+ */
+extern const CFStringRef kSCValNetVPNOnDemandRuleActionConnect;
+
+/*!
+  @const kSCValNetVPNOnDemandRuleActionDisconnect
+  @availability Introduced in Mac OS X 10.8.
+ */
+extern const CFStringRef kSCValNetVPNOnDemandRuleActionDisconnect;
+
+/*!
+  @const kSCValNetVPNOnDemandRuleActionEvaluateConnection
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCValNetVPNOnDemandRuleActionEvaluateConnection;
+
+/*!
+  @const kSCPropNetVPNOnDemandRuleActionParametersDomainAction
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCPropNetVPNOnDemandRuleActionParametersDomainAction;
+
+/*!
+  @const kSCPropNetVPNOnDemandRuleActionParametersDomains
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCPropNetVPNOnDemandRuleActionParametersDomains;
+
+/*!
+  @const kSCPropNetVPNOnDemandRuleActionParametersRequiredDNSServers
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCPropNetVPNOnDemandRuleActionParametersRequiredDNSServers;
+
+/*!
+  @const kSCPropNetVPNOnDemandRuleActionParametersRequiredURLStringProbe
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCPropNetVPNOnDemandRuleActionParametersRequiredURLStringProbe;
+
+/*!
+  @const kSCValNetVPNOnDemandRuleActionParametersDomainActionConnectIfNeeded
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCValNetVPNOnDemandRuleActionParametersDomainActionConnectIfNeeded;
+
+/*!
+  @const kSCValNetVPNOnDemandRuleActionParametersDomainActionNeverConnect
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCValNetVPNOnDemandRuleActionParametersDomainActionNeverConnect;
+
+/*!
+  @const kSCValNetVPNOnDemandRuleInterfaceTypeMatchCellular
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCValNetVPNOnDemandRuleInterfaceTypeMatchCellular;
+
+/*!
+  @const kSCValNetVPNOnDemandRuleInterfaceTypeMatchEthernet
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCValNetVPNOnDemandRuleInterfaceTypeMatchEthernet;
+
+/*!
+  @const kSCValNetVPNOnDemandRuleInterfaceTypeMatchWiFi
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCValNetVPNOnDemandRuleInterfaceTypeMatchWiFi;
+
+/*!
+  @const kSCValNetVPNPluginCapabilityAuth
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCValNetVPNPluginCapabilityAuth;
+
+/*!
+  @const kSCValNetVPNPluginCapabilityConnect
+  @availability Introduced in Mac OS X 10.9.
+ */
+extern const CFStringRef kSCValNetVPNPluginCapabilityConnect;
+
 /*!
   @group kSCCompSystem Properties
  */
@@ -893,12 +1294,24 @@ extern const CFStringRef kSCPropVirtualNetworkInterfacesVLANOptions;
                      ,CFDictionary                                     )
 
 
+  SC_SCHEMA_DECLARATION(kSCEntNetAppLayer, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCEntNetAppLayer                                             \
+         SC_SCHEMA_KV(kSCEntNetAppLayer                                \
+                     ,"AppLayer"                                       \
+                     ,CFDictionary                                     )
+
   SC_SCHEMA_DECLARATION(kSCEntNetEAPOL, __OSX_AVAILABLE_STARTING(__MAC_10_5,__IPHONE_2_0/*SPI*/))
   #define kSCEntNetEAPOL                                                \
          SC_SCHEMA_KV(kSCEntNetEAPOL                                   \
                      ,"EAPOL"                                          \
                      ,CFDictionary                                     )
 
+  SC_SCHEMA_DECLARATION(kSCEntNetLinkIssues, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCEntNetLinkIssues                                           \
+         SC_SCHEMA_KV(kSCEntNetLinkIssues                              \
+                     ,"LinkIssues"                                     \
+                     ,CFDictionary                                     )
+
   SC_SCHEMA_DECLARATION(kSCEntNetLinkQuality, __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_5_0/*SPI*/))
   #define kSCEntNetLinkQuality                                          \
          SC_SCHEMA_KV(kSCEntNetLinkQuality                             \
@@ -936,6 +1349,18 @@ extern const CFStringRef kSCPropVirtualNetworkInterfacesVLANOptions;
                      ,CFBoolean                                        )
 
 
+  SC_SCHEMA_DECLARATION(kSCPropNetDNSServiceIdentifier, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCPropNetDNSServiceIdentifier                                \
+         SC_SCHEMA_KV(kSCPropNetDNSServiceIdentifier                   \
+                     ,"ServiceIdentifier"                              \
+                     ,CFNumber                                         )
+
+  SC_SCHEMA_DECLARATION(kSCPropNetDNSSupplementalMatchDomainsNoSearch, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCPropNetDNSSupplementalMatchDomainsNoSearch                 \
+         SC_SCHEMA_KV(kSCPropNetDNSSupplementalMatchDomainsNoSearch    \
+                     ,"SupplementalMatchDomainsNoSearch"               \
+                     ,CFNumber (0 or 1)                                )
+
   SC_SCHEMA_DECLARATION(kSCPropNetEthernetCapabilityAV, __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_5_0/*SPI*/))
   #define kSCPropNetEthernetCapabilityAV                                \
          SC_SCHEMA_KV(kSCPropNetEthernetCapabilityAV                   \
@@ -1008,6 +1433,18 @@ extern const CFStringRef kSCPropVirtualNetworkInterfacesVLANOptions;
                      ,"VPN"                                            \
                      ,                                                 )
 
+  SC_SCHEMA_DECLARATION(kSCPropNetIPSecDisconnectOnWake, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCPropNetIPSecDisconnectOnWake                               \
+         SC_SCHEMA_KV(kSCPropNetIPSecDisconnectOnWake                  \
+                     ,"DisconnectOnWake"                               \
+                     ,CFNumber (0 or 1)                                )
+
+  SC_SCHEMA_DECLARATION(kSCPropNetIPSecDisconnectOnWakeTimer, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCPropNetIPSecDisconnectOnWakeTimer                          \
+         SC_SCHEMA_KV(kSCPropNetIPSecDisconnectOnWakeTimer             \
+                     ,"DisconnectOnWakeTimer"                          \
+                     ,CFNumber                                         )
+
   SC_SCHEMA_DECLARATION(kSCPropNetIPSecLastCause, __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_3_0/*SPI*/))
   #define kSCPropNetIPSecLastCause                                      \
          SC_SCHEMA_KV(kSCPropNetIPSecLastCause                         \
@@ -1116,12 +1553,42 @@ extern const CFStringRef kSCPropVirtualNetworkInterfacesVLANOptions;
                      ,"GatewayAddress"                                 \
                      ,CFString                                         )
 
+  SC_SCHEMA_DECLARATION(kSCPropNetLinkIssuesModuleID, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCPropNetLinkIssuesModuleID                                  \
+         SC_SCHEMA_KV(kSCPropNetLinkIssuesModuleID                     \
+                     ,"ModuleID"                                       \
+                     ,CFData                                           )
+
+  SC_SCHEMA_DECLARATION(kSCPropNetLinkIssuesInfo, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCPropNetLinkIssuesInfo                                      \
+         SC_SCHEMA_KV(kSCPropNetLinkIssuesInfo                         \
+                     ,"Info"                                           \
+                     ,CFData                                           )
+
+  SC_SCHEMA_DECLARATION(kSCPropNetLinkIssuesTimeStamp, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCPropNetLinkIssuesTimeStamp                                 \
+         SC_SCHEMA_KV(kSCPropNetLinkIssuesTimeStamp                    \
+                     ,"TimeStamp"                                      \
+                     ,CFDATE                                           )
+
   SC_SCHEMA_DECLARATION(kSCPropNetLinkQuality, __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_5_0/*SPI*/))
   #define kSCPropNetLinkQuality                                         \
          SC_SCHEMA_KV(kSCPropNetLinkQuality                            \
                      ,"LinkQuality"                                    \
                      ,CFNumber                                         )
 
+  SC_SCHEMA_DECLARATION(kSCPropNetPPPDisconnectOnWake, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCPropNetPPPDisconnectOnWake                                 \
+         SC_SCHEMA_KV(kSCPropNetPPPDisconnectOnWake                    \
+                     ,"DisconnectOnWake"                               \
+                     ,CFNumber (0 or 1)                                )
+
+  SC_SCHEMA_DECLARATION(kSCPropNetPPPDisconnectOnWakeTimer, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCPropNetPPPDisconnectOnWakeTimer                            \
+         SC_SCHEMA_KV(kSCPropNetPPPDisconnectOnWakeTimer               \
+                     ,"DisconnectOnWakeTimer"                          \
+                     ,CFNumber                                         )
+
   SC_SCHEMA_DECLARATION(kSCPropNetPPPOnDemandDomains, __OSX_AVAILABLE_STARTING(__MAC_10_5,__IPHONE_2_0/*SPI*/))
   #define kSCPropNetPPPOnDemandDomains                                  \
          SC_SCHEMA_KV(kSCPropNetPPPOnDemandDomains                     \
@@ -1206,6 +1673,18 @@ extern const CFStringRef kSCPropVirtualNetworkInterfacesVLANOptions;
                      ,"Low"                                            \
                      ,                                                 )
 
+  SC_SCHEMA_DECLARATION(kSCPropNetProxiesBypassAllowed, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCPropNetProxiesBypassAllowed                                \
+         SC_SCHEMA_KV(kSCPropNetProxiesBypassAllowed                   \
+                     ,"BypassAllowed"                                  \
+                     ,CFNumber (0 or 1)                                )
+
+  SC_SCHEMA_DECLARATION(kSCPropNetProxiesFallBackAllowed, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0/*SPI*/))
+  #define kSCPropNetProxiesFallBackAllowed                              \
+         SC_SCHEMA_KV(kSCPropNetProxiesFallBackAllowed                 \
+                     ,"FallBackAllowed"                                \
+                     ,CFNumber (0 or 1)                                )
+
   SC_SCHEMA_DECLARATION(kSCPropNetProxiesSupplementalMatchDomains, __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_5_0/*SPI*/))
   #define kSCPropNetProxiesSupplementalMatchDomains                     \
          SC_SCHEMA_KV(kSCPropNetProxiesSupplementalMatchDomains        \
@@ -1224,6 +1703,12 @@ extern const CFStringRef kSCPropVirtualNetworkInterfacesVLANOptions;
                      ,"__SCOPED__"                                     \
                      ,CFDictionary                                     )
 
+  SC_SCHEMA_DECLARATION(kSCPropNetProxiesServices, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCPropNetProxiesServices                                     \
+         SC_SCHEMA_KV(kSCPropNetProxiesServices                        \
+                     ,"__SERVICES__"                                   \
+                     ,CFDictionary                                     )
+
   SC_SCHEMA_DECLARATION(kSCPropNetProxiesSupplemental, __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_5_0/*SPI*/))
   #define kSCPropNetProxiesSupplemental                                 \
          SC_SCHEMA_KV(kSCPropNetProxiesSupplemental                    \
@@ -1266,6 +1751,18 @@ extern const CFStringRef kSCPropVirtualNetworkInterfacesVLANOptions;
                      ,"Never"                                          \
                      ,                                                 )
 
+  SC_SCHEMA_DECLARATION(kSCPropNetVPNAppRules, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCPropNetVPNAppRules                                         \
+         SC_SCHEMA_KV(kSCPropNetVPNAppRules                            \
+                     ,"AppRules"                                       \
+                     ,CFArray[CFDictionary]                            )
+
+  SC_SCHEMA_DECLARATION(kSCPropNetVPNAuthCredentialPassword, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCPropNetVPNAuthCredentialPassword                           \
+         SC_SCHEMA_KV(kSCPropNetVPNAuthCredentialPassword              \
+                     ,"AuthCredentialPassword"                         \
+                     ,CFString                                         )
+
   SC_SCHEMA_DECLARATION(kSCPropNetVPNAuthName, __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_4_0/*SPI*/))
   #define kSCPropNetVPNAuthName                                         \
          SC_SCHEMA_KV(kSCPropNetVPNAuthName                            \
@@ -1284,6 +1781,12 @@ extern const CFStringRef kSCPropVirtualNetworkInterfacesVLANOptions;
                      ,"AuthPasswordEncryption"                         \
                      ,CFString                                         )
 
+  SC_SCHEMA_DECLARATION(kSCPropNetVPNAuthPasswordPluginType, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCPropNetVPNAuthPasswordPluginType                           \
+         SC_SCHEMA_KV(kSCPropNetVPNAuthPasswordPluginType              \
+                     ,"AuthPasswordPluginType"                         \
+                     ,CFString                                         )
+
   SC_SCHEMA_DECLARATION(kSCPropNetVPNAuthenticationMethod, __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_4_0/*SPI*/))
   #define kSCPropNetVPNAuthenticationMethod                             \
          SC_SCHEMA_KV(kSCPropNetVPNAuthenticationMethod                \
@@ -1326,6 +1829,18 @@ extern const CFStringRef kSCPropVirtualNetworkInterfacesVLANOptions;
                      ,"DisconnectOnSleep"                              \
                      ,CFNumber (0 or 1)                                )
 
+  SC_SCHEMA_DECLARATION(kSCPropNetVPNDisconnectOnWake, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCPropNetVPNDisconnectOnWake                                 \
+         SC_SCHEMA_KV(kSCPropNetVPNDisconnectOnWake                    \
+                     ,"DisconnectOnWake"                               \
+                     ,CFNumber (0 or 1)                                )
+
+  SC_SCHEMA_DECLARATION(kSCPropNetVPNDisconnectOnWakeTimer, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCPropNetVPNDisconnectOnWakeTimer                            \
+         SC_SCHEMA_KV(kSCPropNetVPNDisconnectOnWakeTimer               \
+                     ,"DisconnectOnWakeTimer"                          \
+                     ,CFNumber                                         )
+
   SC_SCHEMA_DECLARATION(kSCPropNetVPNLocalCertificate, __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_4_0/*SPI*/))
   #define kSCPropNetVPNLocalCertificate                                 \
          SC_SCHEMA_KV(kSCPropNetVPNLocalCertificate                    \
@@ -1350,6 +1865,12 @@ extern const CFStringRef kSCPropVirtualNetworkInterfacesVLANOptions;
                      ,"OnDemandEnabled"                                \
                      ,CFNumber (0 or 1)                                )
 
+  SC_SCHEMA_DECLARATION(kSCPropNetVPNOnDemandMatchAppEnabled, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCPropNetVPNOnDemandMatchAppEnabled                          \
+         SC_SCHEMA_KV(kSCPropNetVPNOnDemandMatchAppEnabled             \
+                     ,"OnDemandMatchAppEnabled"                        \
+                     ,CFBoolean                                        )
+
   SC_SCHEMA_DECLARATION(kSCPropNetVPNOnDemandMatchDomainsAlways, __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_4_0/*SPI*/))
   #define kSCPropNetVPNOnDemandMatchDomainsAlways                       \
          SC_SCHEMA_KV(kSCPropNetVPNOnDemandMatchDomainsAlways          \
@@ -1368,6 +1889,24 @@ extern const CFStringRef kSCPropVirtualNetworkInterfacesVLANOptions;
                      ,"OnDemandMatchDomainsNever"                      \
                      ,CFArray[CFString]                                )
 
+  SC_SCHEMA_DECLARATION(kSCPropNetVPNOnDemandRules, __OSX_AVAILABLE_STARTING(__MAC_10_8,__IPHONE_6_0/*SPI*/))
+  #define kSCPropNetVPNOnDemandRules                                    \
+         SC_SCHEMA_KV(kSCPropNetVPNOnDemandRules                       \
+                     ,"OnDemandRules"                                  \
+                     ,CFArray[CFDictionary]                            )
+
+  SC_SCHEMA_DECLARATION(kSCPropNetVPNOnDemandSuspended, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCPropNetVPNOnDemandSuspended                                \
+         SC_SCHEMA_KV(kSCPropNetVPNOnDemandSuspended                   \
+                     ,"OnDemandSuspended"                              \
+                     ,CFNumber                                         )
+
+  SC_SCHEMA_DECLARATION(kSCPropNetVPNPluginCapability, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCPropNetVPNPluginCapability                                 \
+         SC_SCHEMA_KV(kSCPropNetVPNPluginCapability                    \
+                     ,"PluginCapability"                               \
+                     ,CFString                                         )
+
   SC_SCHEMA_DECLARATION(kSCPropNetVPNRemoteAddress, __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_4_0/*SPI*/))
   #define kSCPropNetVPNRemoteAddress                                    \
          SC_SCHEMA_KV(kSCPropNetVPNRemoteAddress                       \
@@ -1386,6 +1925,42 @@ extern const CFStringRef kSCPropVirtualNetworkInterfacesVLANOptions;
                      ,"VerboseLogging"                                 \
                      ,CFNumber (0 or 1)                                )
 
+  SC_SCHEMA_DECLARATION(kSCValNetVPNAppRuleAccountIdentifierMatch, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCValNetVPNAppRuleAccountIdentifierMatch                     \
+         SC_SCHEMA_KV(kSCValNetVPNAppRuleAccountIdentifierMatch        \
+                     ,"AccountIdentifierMatch"                         \
+                     ,CFArray[CFString]                                )
+
+  SC_SCHEMA_DECLARATION(kSCValNetVPNAppRuleDNSDomainMatch, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCValNetVPNAppRuleDNSDomainMatch                             \
+         SC_SCHEMA_KV(kSCValNetVPNAppRuleDNSDomainMatch                \
+                     ,"DNSDomainMatch"                                 \
+                     ,CFArray[CFString]                                )
+
+  SC_SCHEMA_DECLARATION(kSCValNetVPNAppRuleExecutableMatch, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCValNetVPNAppRuleExecutableMatch                            \
+         SC_SCHEMA_KV(kSCValNetVPNAppRuleExecutableMatch               \
+                     ,"ExecutableMatch"                                \
+                     ,CFArray[CFDictionary]                            )
+
+  SC_SCHEMA_DECLARATION(kSCValNetVPNAppRuleIdentifier, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCValNetVPNAppRuleIdentifier                                 \
+         SC_SCHEMA_KV(kSCValNetVPNAppRuleIdentifier                    \
+                     ,"Identifier"                                     \
+                     ,CFString                                         )
+
+  SC_SCHEMA_DECLARATION(kSCValNetVPNAppRuleExecutableDesignatedRequirement, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCValNetVPNAppRuleExecutableDesignatedRequirement              \
+         SC_SCHEMA_KV(kSCValNetVPNAppRuleExecutableDesignatedRequirement \
+                     ,"DesignatedRequirement"                          \
+                     ,CFString                                         )
+
+  SC_SCHEMA_DECLARATION(kSCValNetVPNAppRuleExecutableSigningIdentifier, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCValNetVPNAppRuleExecutableSigningIdentifier                \
+         SC_SCHEMA_KV(kSCValNetVPNAppRuleExecutableSigningIdentifier   \
+                     ,"SigningIdentifier"                              \
+                     ,CFString                                         )
+
   SC_SCHEMA_DECLARATION(kSCValNetVPNAuthenticationMethodPassword, __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_4_0/*SPI*/))
   #define kSCValNetVPNAuthenticationMethodPassword                      \
          SC_SCHEMA_KV(kSCValNetVPNAuthenticationMethodPassword         \
@@ -1398,6 +1973,12 @@ extern const CFStringRef kSCPropVirtualNetworkInterfacesVLANOptions;
                      ,"Certificate"                                    \
                      ,                                                 )
 
+  SC_SCHEMA_DECLARATION(kSCValNetVPNAuthPasswordEncryptionExternal, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCValNetVPNAuthPasswordEncryptionExternal                    \
+         SC_SCHEMA_KV(kSCValNetVPNAuthPasswordEncryptionExternal       \
+                     ,"External"                                       \
+                     ,                                                 )
+
   SC_SCHEMA_DECLARATION(kSCValNetVPNAuthPasswordEncryptionKeychain, __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_4_0/*SPI*/))
   #define kSCValNetVPNAuthPasswordEncryptionKeychain                    \
          SC_SCHEMA_KV(kSCValNetVPNAuthPasswordEncryptionKeychain       \
@@ -1410,6 +1991,139 @@ extern const CFStringRef kSCPropVirtualNetworkInterfacesVLANOptions;
                      ,"Prompt"                                         \
                      ,                                                 )
 
+  SC_SCHEMA_DECLARATION(kSCPropNetVPNOnDemandRuleAction, __OSX_AVAILABLE_STARTING(__MAC_10_8,__IPHONE_6_0/*SPI*/))
+  #define kSCPropNetVPNOnDemandRuleAction                               \
+         SC_SCHEMA_KV(kSCPropNetVPNOnDemandRuleAction                  \
+                     ,"Action"                                         \
+                     ,CFString                                         )
+
+  SC_SCHEMA_DECLARATION(kSCPropNetVPNOnDemandRuleActionParameters, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCPropNetVPNOnDemandRuleActionParameters                     \
+         SC_SCHEMA_KV(kSCPropNetVPNOnDemandRuleActionParameters        \
+                     ,"ActionParameters"                               \
+                     ,CFArray[CFDictionary]                            )
+
+  SC_SCHEMA_DECLARATION(kSCPropNetVPNOnDemandRuleDNSDomainMatch, __OSX_AVAILABLE_STARTING(__MAC_10_8,__IPHONE_6_0/*SPI*/))
+  #define kSCPropNetVPNOnDemandRuleDNSDomainMatch                       \
+         SC_SCHEMA_KV(kSCPropNetVPNOnDemandRuleDNSDomainMatch          \
+                     ,"DNSDomainMatch"                                 \
+                     ,CFArray[CFString]                                )
+
+  SC_SCHEMA_DECLARATION(kSCPropNetVPNOnDemandRuleDNSServerAddressMatch, __OSX_AVAILABLE_STARTING(__MAC_10_8,__IPHONE_6_0/*SPI*/))
+  #define kSCPropNetVPNOnDemandRuleDNSServerAddressMatch                \
+         SC_SCHEMA_KV(kSCPropNetVPNOnDemandRuleDNSServerAddressMatch   \
+                     ,"DNSServerAddressMatch"                          \
+                     ,CFArray[CFString]                                )
+
+  SC_SCHEMA_DECLARATION(kSCPropNetVPNOnDemandRuleSSIDMatch, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCPropNetVPNOnDemandRuleSSIDMatch                            \
+         SC_SCHEMA_KV(kSCPropNetVPNOnDemandRuleSSIDMatch               \
+                     ,"SSIDMatch"                                      \
+                     ,CFArray[CFString]                                )
+
+  SC_SCHEMA_DECLARATION(kSCPropNetVPNOnDemandRuleInterfaceTypeMatch, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCPropNetVPNOnDemandRuleInterfaceTypeMatch                   \
+         SC_SCHEMA_KV(kSCPropNetVPNOnDemandRuleInterfaceTypeMatch      \
+                     ,"InterfaceTypeMatch"                             \
+                     ,CFString                                         )
+
+  SC_SCHEMA_DECLARATION(kSCPropNetVPNOnDemandRuleURLStringProbe, __OSX_AVAILABLE_STARTING(__MAC_10_8,__IPHONE_6_0/*SPI*/))
+  #define kSCPropNetVPNOnDemandRuleURLStringProbe                       \
+         SC_SCHEMA_KV(kSCPropNetVPNOnDemandRuleURLStringProbe          \
+                     ,"URLStringProbe"                                 \
+                     ,CFString                                         )
+
+  SC_SCHEMA_DECLARATION(kSCValNetVPNOnDemandRuleActionAllow, __OSX_AVAILABLE_STARTING(__MAC_10_8,__IPHONE_6_0/*SPI*/))
+  #define kSCValNetVPNOnDemandRuleActionAllow                           \
+         SC_SCHEMA_KV(kSCValNetVPNOnDemandRuleActionAllow              \
+                     ,"Allow"                                          \
+                     ,                                                 )
+
+  SC_SCHEMA_DECLARATION(kSCValNetVPNOnDemandRuleActionIgnore, __OSX_AVAILABLE_STARTING(__MAC_10_8,__IPHONE_6_0/*SPI*/))
+  #define kSCValNetVPNOnDemandRuleActionIgnore                          \
+         SC_SCHEMA_KV(kSCValNetVPNOnDemandRuleActionIgnore             \
+                     ,"Ignore"                                         \
+                     ,                                                 )
+
+  SC_SCHEMA_DECLARATION(kSCValNetVPNOnDemandRuleActionConnect, __OSX_AVAILABLE_STARTING(__MAC_10_8,__IPHONE_6_0/*SPI*/))
+  #define kSCValNetVPNOnDemandRuleActionConnect                         \
+         SC_SCHEMA_KV(kSCValNetVPNOnDemandRuleActionConnect            \
+                     ,"Connect"                                        \
+                     ,                                                 )
+
+  SC_SCHEMA_DECLARATION(kSCValNetVPNOnDemandRuleActionDisconnect, __OSX_AVAILABLE_STARTING(__MAC_10_8,__IPHONE_6_0/*SPI*/))
+  #define kSCValNetVPNOnDemandRuleActionDisconnect                      \
+         SC_SCHEMA_KV(kSCValNetVPNOnDemandRuleActionDisconnect         \
+                     ,"Disconnect"                                     \
+                     ,                                                 )
+
+  SC_SCHEMA_DECLARATION(kSCValNetVPNOnDemandRuleActionEvaluateConnection, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCValNetVPNOnDemandRuleActionEvaluateConnection              \
+         SC_SCHEMA_KV(kSCValNetVPNOnDemandRuleActionEvaluateConnection \
+                     ,"EvaluateConnection"                             \
+                     ,                                                 )
+
+  SC_SCHEMA_DECLARATION(kSCPropNetVPNOnDemandRuleActionParametersDomainAction, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCPropNetVPNOnDemandRuleActionParametersDomainAction              \
+         SC_SCHEMA_KV(kSCPropNetVPNOnDemandRuleActionParametersDomainAction \
+                     ,"DomainAction"                                   \
+                     ,CFString                                         )
+
+  SC_SCHEMA_DECLARATION(kSCPropNetVPNOnDemandRuleActionParametersDomains, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCPropNetVPNOnDemandRuleActionParametersDomains              \
+         SC_SCHEMA_KV(kSCPropNetVPNOnDemandRuleActionParametersDomains \
+                     ,"Domains"                                        \
+                     ,CFArray[CFString]                                )
+
+  SC_SCHEMA_DECLARATION(kSCPropNetVPNOnDemandRuleActionParametersRequiredDNSServers, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCPropNetVPNOnDemandRuleActionParametersRequiredDNSServers              \
+         SC_SCHEMA_KV(kSCPropNetVPNOnDemandRuleActionParametersRequiredDNSServers \
+                     ,"RequiredDNSServers"                             \
+                     ,CFArray[CFString]                                )
+
+  SC_SCHEMA_DECLARATION(kSCPropNetVPNOnDemandRuleActionParametersRequiredURLStringProbe, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCPropNetVPNOnDemandRuleActionParametersRequiredURLStringProbe              \
+         SC_SCHEMA_KV(kSCPropNetVPNOnDemandRuleActionParametersRequiredURLStringProbe \
+                     ,"RequiredURLStringProbe"                         \
+                     ,CFString                                         )
+
+  SC_SCHEMA_DECLARATION(kSCValNetVPNOnDemandRuleActionParametersDomainActionConnectIfNeeded, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCValNetVPNOnDemandRuleActionParametersDomainActionConnectIfNeeded              \
+         SC_SCHEMA_KV(kSCValNetVPNOnDemandRuleActionParametersDomainActionConnectIfNeeded \
+                     ,"ConnectIfNeeded"                                \
+                     ,                                                 )
+
+  SC_SCHEMA_DECLARATION(kSCValNetVPNOnDemandRuleActionParametersDomainActionNeverConnect, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCValNetVPNOnDemandRuleActionParametersDomainActionNeverConnect              \
+         SC_SCHEMA_KV(kSCValNetVPNOnDemandRuleActionParametersDomainActionNeverConnect \
+                     ,"NeverConnect"                                   \
+                     ,                                                 )
+
+
+  SC_SCHEMA_DECLARATION(kSCValNetVPNOnDemandRuleInterfaceTypeMatchEthernet, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCValNetVPNOnDemandRuleInterfaceTypeMatchEthernet              \
+         SC_SCHEMA_KV(kSCValNetVPNOnDemandRuleInterfaceTypeMatchEthernet \
+                     ,"Ethernet"                                       \
+                     ,                                                 )
+
+  SC_SCHEMA_DECLARATION(kSCValNetVPNOnDemandRuleInterfaceTypeMatchWiFi, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCValNetVPNOnDemandRuleInterfaceTypeMatchWiFi                \
+         SC_SCHEMA_KV(kSCValNetVPNOnDemandRuleInterfaceTypeMatchWiFi   \
+                     ,"WiFi"                                           \
+                     ,                                                 )
+
+  SC_SCHEMA_DECLARATION(kSCValNetVPNPluginCapabilityAuth, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCValNetVPNPluginCapabilityAuth                              \
+         SC_SCHEMA_KV(kSCValNetVPNPluginCapabilityAuth                 \
+                     ,"Auth"                                           \
+                     ,                                                 )
+
+  SC_SCHEMA_DECLARATION(kSCValNetVPNPluginCapabilityConnect, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))
+  #define kSCValNetVPNPluginCapabilityConnect                           \
+         SC_SCHEMA_KV(kSCValNetVPNPluginCapabilityConnect              \
+                     ,"Connect"                                        \
+                     ,                                                 )
+
   SC_SCHEMA_DECLARATION(kSCPropSystemComputerNameRegion, __OSX_AVAILABLE_STARTING(__MAC_10_5,__IPHONE_2_0/*SPI*/))
   #define kSCPropSystemComputerNameRegion                               \
          SC_SCHEMA_KV(kSCPropSystemComputerNameRegion                  \
diff --git a/SystemConfiguration.fproj/SNHelper.c b/SystemConfiguration.fproj/SNHelper.c
new file mode 100644 (file)
index 0000000..4ae0fd9
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2013 Apple Inc.
+ * All rights reserved.
+ */
+#include <errno.h>
+#include <syslog.h>
+#include <xpc/xpc.h>
+
+#include "SNHelperPrivate.h"
+
+static xpc_connection_t
+create_connection(dispatch_queue_t queue)
+{
+       xpc_connection_t new_connection;
+
+       new_connection = xpc_connection_create_mach_service(kSNHelperService, queue, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED);
+       if (isa_xpc_connection(new_connection)) {
+               xpc_connection_set_event_handler(new_connection,
+                       ^(xpc_object_t message) {
+                               if (isa_xpc_error(message)) {
+                                       syslog(LOG_INFO, "Got an error on the snhelper connection");
+                               } else if (isa_xpc_dictionary(message)) {
+                                       syslog(LOG_INFO, "Got an unexpected message on the snhelper connection");
+                               }
+                       });
+               xpc_connection_resume(new_connection);
+       }
+
+       return new_connection;
+}
+
+static xpc_object_t
+copy_response(xpc_object_t request)
+{
+       dispatch_queue_t conn_queue = dispatch_queue_create("snhelper request", NULL);
+       xpc_connection_t connection = create_connection(conn_queue);
+       xpc_object_t response = NULL;
+
+       if (connection) {
+               response = xpc_connection_send_message_with_reply_sync(connection, request);
+               xpc_connection_cancel(connection);
+               xpc_release(connection);
+       }
+
+       dispatch_release(conn_queue);
+
+       return response;
+}
+
+static int
+flow_divert_uuid_policy_operate(const uuid_t uuid, int operation)
+{
+       int result = 0;
+       xpc_object_t request = xpc_dictionary_create(NULL, NULL, 0);
+       xpc_object_t response;
+
+       xpc_dictionary_set_uint64(request, kSNHelperMessageType, operation);
+       xpc_dictionary_set_uuid(request, kSNHelperMessageUUID, uuid);
+
+       response = copy_response(request);
+
+       if (isa_xpc_dictionary(response)) {
+               result = xpc_dictionary_get_int64(request, kSNHelperMessageResult);
+       } else {
+               result = EINVAL;
+       }
+
+       xpc_release(response);
+       xpc_release(request);
+
+       return result;
+}
+
+int
+snhelper_flow_divert_uuid_policy_add(const uuid_t uuid)
+{
+       return flow_divert_uuid_policy_operate(uuid, kSNHelperMessageTypeFlowDivertUUIDAdd);
+}
+
+int
+snhelper_flow_divert_uuid_policy_remove(const uuid_t uuid)
+{
+       return flow_divert_uuid_policy_operate(uuid, kSNHelperMessageTypeFlowDivertUUIDRemove);
+}
+
+int
+snhelper_flow_divert_uuid_policy_clear(void)
+{
+       int result = 0;
+       xpc_object_t request = xpc_dictionary_create(NULL, NULL, 0);
+       xpc_object_t response;
+
+       xpc_dictionary_set_uint64(request, kSNHelperMessageType, kSNHelperMessageTypeFlowDivertUUIDClear);
+
+       response = copy_response(request);
+
+       if (isa_xpc_dictionary(response)) {
+               result = xpc_dictionary_get_int64(request, kSNHelperMessageResult);
+       } else {
+               result = EINVAL;
+       }
+
+       xpc_release(response);
+       xpc_release(request);
+
+       return result;
+}
+
+static bool
+isa_xpc_object_of_type(xpc_object_t obj, xpc_type_t type)
+{
+       return (obj != NULL && xpc_get_type(obj) == type);
+}
+
+bool
+isa_xpc_connection(xpc_object_t obj)
+{
+       return isa_xpc_object_of_type(obj, XPC_TYPE_CONNECTION);
+}
+
+bool
+isa_xpc_bool(xpc_object_t obj)
+{
+       return isa_xpc_object_of_type(obj, XPC_TYPE_BOOL);
+}
+
+bool
+isa_xpc_dictionary(xpc_object_t obj)
+{
+       return isa_xpc_object_of_type(obj, XPC_TYPE_DICTIONARY);
+}
+
+bool
+isa_xpc_error(xpc_object_t obj)
+{
+       return isa_xpc_object_of_type(obj, XPC_TYPE_ERROR);
+}
+
diff --git a/SystemConfiguration.fproj/SNHelperPrivate.h b/SystemConfiguration.fproj/SNHelperPrivate.h
new file mode 100644 (file)
index 0000000..4d2aefb
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2013 Apple Inc.
+ * All rights reserved.
+ */
+
+#ifndef __SYSTEMCONFIGURATION_SNHELPER_PRIVATE_H__
+#define __SYSTEMCONFIGURATION_SNHELPER_PRIVATE_H__
+
+#include <xpc/xpc.h>
+
+#define kSNHelperService               "com.apple.snhelper"
+
+#define kSNHelperMessageType   "message-type"
+#define kSNHelperMessageUUID   "uuid"
+#define kSNHelperMessageResult "result-code"
+
+enum {
+       kSNHelperMessageTypeFlowDivertUUIDAdd,
+       kSNHelperMessageTypeFlowDivertUUIDRemove,
+       kSNHelperMessageTypeFlowDivertUUIDClear,
+};
+
+int snhelper_flow_divert_uuid_policy_add(const uuid_t uuid);
+int snhelper_flow_divert_uuid_policy_remove(const uuid_t uuid);
+int snhelper_flow_divert_uuid_policy_clear(void);
+
+bool isa_xpc_connection(xpc_object_t obj);
+bool isa_xpc_bool(xpc_object_t obj);
+bool isa_xpc_dictionary(xpc_object_t obj);
+bool isa_xpc_error(xpc_object_t obj);
+
+#endif /* __SYSTEMCONFIGURATION_SNHELPER_PRIVATE_H__ */
index a1337bd7631e5f60185eca300768681d9c7e672f..9cb4bc2740aab3a846b6ff1d8254457068ceec35 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2004, 2006, 2008-2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2004, 2006, 2008-2010, 2012 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -109,6 +109,9 @@ enum {
        kSCStatusConnectionNoService            = 5001, /* Network service for connection not available
                                                           __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_2_0)
                                                         */
+       kSCStatusConnectionIgnore               = 5002, /* Network connection information not available at this time
+                                                          __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0)
+                                                        */
 };
 
 
index a73c9100e709f1fd99ed1cd23f58258e9a2efd55..dc073605700584e0612681b8665a194f1e180127 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2003-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -104,10 +104,21 @@ add_configured_interface(const void *key, const void *value, void *context)
 
        // create the VLAN interface
        vlan = (SCVLANInterfaceRef)_SCVLANInterfaceCreatePrivate(NULL, vlan_if);
+       assert(vlan != NULL);
 
        // set physical interface and tag
        vlan_physical = _SCNetworkInterfaceCreateWithBSDName(NULL, vlan_physical_if,
                                                             kIncludeBondInterfaces);
+       assert(vlan_physical != NULL);
+
+       // since we KNOW that the physical interface supported VLANs when
+       // it was first established it's OK to force that state here ...
+       // and this is needed for the case when the interface (e.g. a
+       // dongle) is not currently attached to the system
+       interfacePrivate = (SCNetworkInterfacePrivateRef)vlan_physical;
+       interfacePrivate->supportsVLAN = TRUE;
+
+       // and now we associate the physical interface and tag
        SCVLANInterfaceSetPhysicalInterfaceAndTag(vlan, vlan_physical, vlan_tag);
        CFRelease(vlan_physical);
 
@@ -134,126 +145,6 @@ add_configured_interface(const void *key, const void *value, void *context)
 }
 
 
-static void
-add_legacy_configuration(addContextRef myContext)
-{
-       CFIndex                         i;
-       CFIndex                         n;
-       SCPreferencesRef                prefs;
-       CFArrayRef                      vlans;
-
-#define VLAN_PREFERENCES_ID            CFSTR("VirtualNetworkInterfaces.plist")
-#define        VLAN_PREFERENCES_VLANS          CFSTR("VLANs")
-#define        __kVLANInterface_interface      CFSTR("interface")      // e.g. vlan0, vlan1, ...
-#define        __kVLANInterface_device         CFSTR("device")         // e.g. en0, en1, ...
-#define __kVLANInterface_tag           CFSTR("tag")            // e.g. 1 <= tag <= 4094
-#define __kVLANInterface_options       CFSTR("options")        // e.g. UserDefinedName
-
-       prefs = SCPreferencesCreate(NULL, CFSTR("SCVLANInterfaceCopyAll"), VLAN_PREFERENCES_ID);
-       if (prefs == NULL) {
-               return;
-       }
-
-       vlans = SCPreferencesGetValue(prefs, VLAN_PREFERENCES_VLANS);
-       if ((vlans != NULL) && !isA_CFArray(vlans)) {
-               CFRelease(prefs);       // if the prefs are confused
-               return;
-       }
-
-       n = (vlans != NULL) ? CFArrayGetCount(vlans) : 0;
-       for (i = 0; i < n; i++) {
-               CFDictionaryRef                 dict;
-               SCNetworkInterfacePrivateRef    interfacePrivate;
-               Boolean                         ok;
-               CFDictionaryRef                 options;
-               CFStringRef                     path;
-               SCVLANInterfaceRef              vlan;
-               CFStringRef                     vlan_if;
-               CFDictionaryRef                 vlan_dict;
-               SCNetworkInterfaceRef           vlan_physical;
-               CFStringRef                     vlan_physical_if;
-               CFNumberRef                     vlan_tag;
-
-               vlan_dict = CFArrayGetValueAtIndex(vlans, i);
-               if (!isA_CFDictionary(vlan_dict)) {
-                       continue;       // if the prefs are confused
-               }
-
-               vlan_if = CFDictionaryGetValue(vlan_dict, __kVLANInterface_interface);
-               if (!isA_CFString(vlan_if)) {
-                       continue;       // if the prefs are confused
-               }
-
-               vlan_physical_if = CFDictionaryGetValue(vlan_dict, __kVLANInterface_device);
-               if (!isA_CFString(vlan_physical_if)) {
-                       continue;       // if the prefs are confused
-               }
-
-               vlan_tag = CFDictionaryGetValue(vlan_dict, __kVLANInterface_tag);
-               if (!isA_CFNumber(vlan_tag)) {
-                       continue;       // if the prefs are confused
-               }
-
-               // check if this VLAN interface has already been allocated
-               path = CFStringCreateWithFormat(NULL,
-                                               NULL,
-                                               CFSTR("/%@/%@/%@"),
-                                               kSCPrefVirtualNetworkInterfaces,
-                                               kSCNetworkInterfaceTypeVLAN,
-                                               vlan_if);
-               dict = SCPreferencesPathGetValue(myContext->prefs, path);
-               if (dict != NULL) {
-                       // if VLAN interface name not available
-                       CFRelease(path);
-                       continue;
-               }
-
-               // add a placeholder for the VLAN in the stored preferences
-               dict = CFDictionaryCreate(NULL,
-                                         NULL, NULL, 0,
-                                         &kCFTypeDictionaryKeyCallBacks,
-                                         &kCFTypeDictionaryValueCallBacks);
-               ok = SCPreferencesPathSetValue(myContext->prefs, path, dict);
-               CFRelease(dict);
-               CFRelease(path);
-               if (!ok) {
-                       // if the VLAN could not be saved
-                       continue;
-               }
-
-               // create the VLAN interface
-               vlan = (SCVLANInterfaceRef)_SCVLANInterfaceCreatePrivate(NULL, vlan_if);
-
-               // estabish link to the stored configuration
-               interfacePrivate = (SCNetworkInterfacePrivateRef)vlan;
-               interfacePrivate->prefs = CFRetain(myContext->prefs);
-
-               // set the interface and tag (which updates the stored preferences)
-               vlan_physical = _SCNetworkInterfaceCreateWithBSDName(NULL, vlan_physical_if,
-                                                                    kIncludeBondInterfaces);
-               SCVLANInterfaceSetPhysicalInterfaceAndTag(vlan, vlan_physical, vlan_tag);
-               CFRelease(vlan_physical);
-
-               // set display name (which updates the stored preferences)
-               options = CFDictionaryGetValue(vlan_dict, __kVLANInterface_options);
-               if (isA_CFDictionary(options)) {
-                       CFStringRef     vlan_name;
-
-                       vlan_name = CFDictionaryGetValue(options, CFSTR("VLAN Name"));
-                       if (isA_CFString(vlan_name)) {
-                               SCVLANInterfaceSetLocalizedDisplayName(vlan, vlan_name);
-                       }
-               }
-
-               CFArrayAppendValue(myContext->vlans, vlan);
-               CFRelease(vlan);
-       }
-
-       CFRelease(prefs);
-       return;
-}
-
-
 static SCVLANInterfaceRef
 findVLANInterfaceAndTag(SCPreferencesRef prefs, SCNetworkInterfaceRef physical, CFNumberRef tag)
 {
@@ -299,6 +190,22 @@ findVLANInterfaceAndTag(SCPreferencesRef prefs, SCNetworkInterfaceRef physical,
 #pragma mark SCVLANInterface APIs
 
 
+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;
+}
+
+
 CFArrayRef
 SCVLANInterfaceCopyAll(SCPreferencesRef prefs)
 {
@@ -315,20 +222,10 @@ SCVLANInterfaceCopyAll(SCPreferencesRef prefs)
                                        kSCPrefVirtualNetworkInterfaces,
                                        kSCNetworkInterfaceTypeVLAN);
        dict = SCPreferencesPathGetValue(prefs, path);
+       CFRelease(path);
        if (isA_CFDictionary(dict)) {
-               CFDictionaryApplyFunction(dict, add_configured_interface, &context);
-       } else {
-               // no VLAN configuration, upgrade from legacy configuration
-               dict = CFDictionaryCreate(NULL,
-                                         NULL, NULL, 0,
-                                         &kCFTypeDictionaryKeyCallBacks,
-                                         &kCFTypeDictionaryValueCallBacks);
-               (void) SCPreferencesPathSetValue(prefs, path, dict);
-               CFRelease(dict);
-
-               add_legacy_configuration(&context);
+               my_CFDictionaryApplyFunction(dict, add_configured_interface, &context);
        }
-       CFRelease(path);
 
        return context.vlans;
 }
@@ -481,6 +378,7 @@ _SCVLANInterfaceCopyActive(void)
                // create the VLAN interface
                vlan_if = CFStringCreateWithCString(NULL, ifp->ifa_name, kCFStringEncodingASCII);
                vlan    = (SCVLANInterfaceRef)_SCVLANInterfaceCreatePrivate(NULL, vlan_if);
+               assert(vlan != NULL);
                CFRelease(vlan_if);
 
                // set the physical interface and tag
@@ -488,10 +386,12 @@ _SCVLANInterfaceCopyActive(void)
                vlan_physical_if = CFStringCreateWithCString(NULL, vlr_parent, kCFStringEncodingASCII);
                vlan_physical = _SCNetworkInterfaceCreateWithBSDName(NULL, vlan_physical_if,
                                                                     kIncludeBondInterfaces);
+               assert(vlan_physical != NULL);
                CFRelease(vlan_physical_if);
 
                vlr_tag  = vreq.vlr_tag;
                vlan_tag = CFNumberCreate(NULL, kCFNumberIntType, &vlr_tag);
+               assert(vlan_tag != NULL);
 
                SCVLANInterfaceSetPhysicalInterfaceAndTag(vlan, vlan_physical, vlan_tag);
                CFRelease(vlan_physical);
@@ -504,7 +404,9 @@ _SCVLANInterfaceCopyActive(void)
 
     done :
 
-       (void) close(s);
+       if (s != -1) {
+               (void) close(s);
+       }
        freeifaddrs(ifap);
        return vlans;
 }
@@ -564,7 +466,7 @@ SCVLANInterfaceCreate(SCPreferencesRef prefs, SCNetworkInterfaceRef physical, CF
                Boolean                         ok;
                CFStringRef                     path;
 
-               vlan_if = CFStringCreateWithFormat(allocator, NULL, CFSTR("vlan%d"), i);
+               vlan_if = CFStringCreateWithFormat(allocator, NULL, CFSTR("vlan%ld"), i);
                path    = CFStringCreateWithFormat(allocator,
                                                   NULL,
                                                   CFSTR("/%@/%@/%@"),
@@ -757,7 +659,9 @@ SCVLANInterfaceSetPhysicalInterfaceAndTag(SCVLANInterfaceRef vlan, SCNetworkInte
                                     kSCPropVirtualNetworkInterfacesVLANInterface,
                                     SCNetworkInterfaceGetBSDName(physical));
                CFDictionarySetValue(newDict, kSCPropVirtualNetworkInterfacesVLANTag, tag);
-               ok = SCPreferencesPathSetValue(interfacePrivate->prefs, path, newDict);
+               if (!CFEqual(dict, newDict)) {
+                       ok = SCPreferencesPathSetValue(interfacePrivate->prefs, path, newDict);
+               }
                CFRelease(newDict);
                CFRelease(path);
        }
@@ -827,7 +731,9 @@ SCVLANInterfaceSetLocalizedDisplayName(SCVLANInterfaceRef vlan, CFStringRef newN
                } else {
                        CFDictionaryRemoveValue(newDict, kSCPropUserDefinedName);
                }
-               ok = SCPreferencesPathSetValue(interfacePrivate->prefs, path, newDict);
+               if (!CFEqual(dict, newDict)) {
+                       ok = SCPreferencesPathSetValue(interfacePrivate->prefs, path, newDict);
+               }
                CFRelease(newDict);
                CFRelease(path);
        }
@@ -889,7 +795,9 @@ SCVLANInterfaceSetOptions(SCVLANInterfaceRef vlan, CFDictionaryRef newOptions)
                } else {
                        CFDictionaryRemoveValue(newDict, kSCPropVirtualNetworkInterfacesVLANOptions);
                }
-               ok = SCPreferencesPathSetValue(interfacePrivate->prefs, path, newDict);
+               if (!CFEqual(dict, newDict)) {
+                       ok = SCPreferencesPathSetValue(interfacePrivate->prefs, path, newDict);
+               }
                CFRelease(newDict);
                CFRelease(path);
        }
diff --git a/SystemConfiguration.fproj/VPNAppLayer.c b/SystemConfiguration.fproj/VPNAppLayer.c
new file mode 100644 (file)
index 0000000..01901ca
--- /dev/null
@@ -0,0 +1,5 @@
+/*
+ * Copyright (c) 2012, 2013 Apple Inc.
+ * All rights reserved.
+ */
+
diff --git a/SystemConfiguration.fproj/VPNAppLayerPrivate.h b/SystemConfiguration.fproj/VPNAppLayerPrivate.h
new file mode 100644 (file)
index 0000000..01901ca
--- /dev/null
@@ -0,0 +1,5 @@
+/*
+ * Copyright (c) 2012, 2013 Apple Inc.
+ * All rights reserved.
+ */
+
index 4e587a2ed67ba9e4914e36ce87ed3c91771ccc12..58acb55566492ca3c3a57fce6e6e7c18a8057c92 100644 (file)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2009-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2009-2013 Apple Inc. All rights reserved.
  */
 
index 4e587a2ed67ba9e4914e36ce87ed3c91771ccc12..d7d8fa0247537b254d6d0a6a92931ff2d699c006 100644 (file)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2009-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2009-2011, 2013 Apple Inc. All rights reserved.
  */
 
diff --git a/SystemConfiguration.fproj/VPNFlow.c b/SystemConfiguration.fproj/VPNFlow.c
new file mode 100644 (file)
index 0000000..d286c3d
--- /dev/null
@@ -0,0 +1,4 @@
+/*
+ * Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+ */
+
diff --git a/SystemConfiguration.fproj/VPNFlow.h b/SystemConfiguration.fproj/VPNFlow.h
new file mode 100644 (file)
index 0000000..d286c3d
--- /dev/null
@@ -0,0 +1,4 @@
+/*
+ * Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+ */
+
diff --git a/SystemConfiguration.fproj/VPNFlowPrivate.h b/SystemConfiguration.fproj/VPNFlowPrivate.h
new file mode 100644 (file)
index 0000000..a24886f
--- /dev/null
@@ -0,0 +1,4 @@
+/*
+ * Copyright (c) 2012, 2013 Apple Inc. All rights reserved.
+ */
+
index 2dfbed31dbaa81a2f2ce0217b4c23efcf99867bb..b4b9a4b6b4ec02e87eb5e9c9b04c3f2843e05968 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2009-2013 Apple Inc. All rights reserved.
  */
 
 
diff --git a/SystemConfiguration.fproj/VPNService.c b/SystemConfiguration.fproj/VPNService.c
new file mode 100644 (file)
index 0000000..8be02b4
--- /dev/null
@@ -0,0 +1,423 @@
+/*
+ * Copyright (c) 2012, 2013 Apple Inc. All rights reserved.
+ */
+
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SCPrivate.h>
+
+static Boolean
+isA_VPNService(CFTypeRef cf)
+{
+       if (isA_SCNetworkService(cf)) {
+               SCNetworkInterfaceRef   interface = SCNetworkServiceGetInterface((SCNetworkServiceRef)cf);
+
+               return (interface != NULL &&
+                       CFEqual(SCNetworkInterfaceGetInterfaceType(interface), kSCNetworkInterfaceTypeVPN));
+       }
+
+       return FALSE;
+}
+
+
+static CFArrayRef
+copy_matching_services(SCPreferencesRef prefs, CFStringRef identifierDomain, CFStringRef identifier)
+{
+       CFMutableArrayRef       results         = NULL;
+       CFArrayRef                      services;
+
+       services = SCNetworkServiceCopyAll(prefs);
+       if (services != NULL) {
+               CFIndex idx;
+               CFIndex service_count = CFArrayGetCount(services);
+
+               for (idx = 0; idx < service_count; idx++) {
+                       SCNetworkServiceRef             service = CFArrayGetValueAtIndex(services, idx);
+                       Boolean                                 matches = FALSE;
+
+                       if (isA_VPNService(service)) {
+                               if (isA_CFString(identifierDomain) && isA_CFString(identifier)) {
+                                       CFStringRef     ex_identifier = SCNetworkServiceCopyExternalID(service, identifierDomain);
+                                       if (ex_identifier != NULL) {
+                                               matches = CFEqual(ex_identifier, identifier);
+                                               CFRelease(ex_identifier);
+                                       }
+                               } else {
+                                       matches = TRUE;
+                               }
+                       }
+
+                       if (matches) {
+                               if (results == NULL) {
+                                       results = CFArrayCreateMutable(kCFAllocatorDefault, CFArrayGetCount(services) - idx, &kCFTypeArrayCallBacks);
+                               }
+                               CFArrayAppendValue(results, service);
+                       }
+               }
+
+               CFRelease(services);
+       }
+
+       return results;
+}
+
+
+static CFIndex
+find_app_rule(CFDictionaryRef vpn_config, CFStringRef ruleIdentifier)
+{
+       CFArrayRef      app_rules = CFDictionaryGetValue(vpn_config, kSCPropNetVPNAppRules);
+       CFIndex         idx;
+
+       if (isA_CFArray(app_rules)) {
+               CFIndex rule_count = CFArrayGetCount(app_rules);
+
+               for (idx = 0; idx < rule_count; idx++) {
+                       CFDictionaryRef rule = CFArrayGetValueAtIndex(app_rules, idx);
+
+                       if (isA_CFDictionary(rule)) {
+                               CFStringRef     rule_id = CFDictionaryGetValue(rule, kSCValNetVPNAppRuleIdentifier);
+
+                               if (CFEqual(ruleIdentifier, rule_id)) {
+                                       return idx;
+                               }
+                       }
+               }
+       }
+
+       return -1;
+}
+
+static Boolean
+validate_app_rule(CFDictionaryRef ruleSettings)
+{
+       CFIndex         account_count;
+       CFArrayRef      accounts;
+       Boolean         accounts_valid = FALSE;
+       CFArrayRef      executables;
+       Boolean         executables_valid = FALSE;
+       CFIndex         executable_count;
+       CFIndex         idx;
+       CFArrayRef      match_domains;
+
+       if (!isA_CFDictionary(ruleSettings)) {
+               return FALSE;
+       }
+
+       /* Validate the executable array. It needs to have at least one value. */
+       executables = CFDictionaryGetValue(ruleSettings, kSCValNetVPNAppRuleExecutableMatch);
+       if (isA_CFArray(executables) && (executable_count = CFArrayGetCount(executables)) > 0) {
+               executables_valid = TRUE;
+               for (idx = 0; idx < executable_count; idx++) {
+                       CFDictionaryRef executable      = CFArrayGetValueAtIndex(executables, idx);
+
+                       if (isA_CFDictionary(executable)) {
+                               CFStringRef             signingID       = CFDictionaryGetValue(executable, kSCValNetVPNAppRuleExecutableSigningIdentifier);
+                               CFStringRef             requirement     = CFDictionaryGetValue(executable, kSCValNetVPNAppRuleExecutableDesignatedRequirement);
+
+                               if (!isA_CFString(signingID) || CFStringGetLength(signingID) == 0) {
+                                       executables_valid = FALSE;
+                                       break;
+                               }
+
+                               if (requirement != NULL) {
+                                       if (!isA_CFString(requirement) || CFStringGetLength(requirement) == 0) {
+                                               executables_valid = FALSE;
+                                               break;
+                                       }
+#if !TARGET_OS_IPHONE
+                               } else {
+                                       executables_valid = FALSE;
+                                       break;
+#endif /* !TARGET_OS_IPHONE */
+                               }
+                       }
+               }
+       }
+
+       /* Validate the accounts array. It needs to have at least one value. */
+       accounts = CFDictionaryGetValue(ruleSettings, kSCValNetVPNAppRuleAccountIdentifierMatch);
+       if (isA_CFArray(accounts) && (account_count = CFArrayGetCount(accounts)) > 0) {
+               accounts_valid = TRUE;
+               for (idx = 0; idx < account_count; idx++) {
+                       CFStringRef     account = CFArrayGetValueAtIndex(accounts, idx);
+                       if (!isA_CFString(account)) {
+                               accounts_valid = FALSE;
+                               break;
+                       }
+               }
+       }
+
+       /* Either executables or accounts must be present */
+       if (!executables_valid && !accounts_valid) {
+               return FALSE;
+       }
+
+       /* Validate the domains array. It's optional, so just make sure that it contains only strings if it's present. */
+       match_domains = CFDictionaryGetValue(ruleSettings, kSCValNetVPNAppRuleDNSDomainMatch);
+       if (match_domains != NULL) {
+               CFIndex match_domain_count;
+
+               if (!isA_CFArray(match_domains)) {
+                       return FALSE;
+               }
+
+               match_domain_count = CFArrayGetCount(match_domains);
+               for (idx = 0; idx < match_domain_count; idx++) {
+                       CFStringRef     domain  = CFArrayGetValueAtIndex(match_domains, idx);
+                       if (!isA_CFString(domain)) {
+                               return FALSE;
+                       }
+               }
+       }
+
+       return TRUE;
+}
+
+
+CFArrayRef
+VPNServiceCopyAllMatchingExternalID(SCPreferencesRef prefs, CFStringRef identifierDomain, CFStringRef identifier)
+{
+       CFArrayRef      services;
+
+       if (prefs == NULL || !isA_CFString(identifierDomain) || !isA_CFString(identifier)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return NULL;
+       }
+
+       services = copy_matching_services(prefs, identifierDomain, identifier);
+       if (services == NULL) {
+               _SCErrorSet(kSCStatusOK);
+       }
+
+       return services;
+}
+
+
+CFArrayRef
+VPNServiceCopyAll(SCPreferencesRef prefs)
+{
+       CFArrayRef      services;
+
+       if (prefs == NULL) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return NULL;
+       }
+
+       services = copy_matching_services(prefs, NULL, NULL);
+       if (services == NULL) {
+               _SCErrorSet(kSCStatusOK);
+       }
+
+       return services;
+}
+
+
+CFArrayRef
+VPNServiceCopyAppRuleIDs(VPNServiceRef service)
+{
+       CFMutableArrayRef               results         = NULL;
+       CFDictionaryRef                 vpn_config;
+
+       if (!isA_VPNService(service)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return NULL;
+       }
+
+       vpn_config = SCNetworkInterfaceGetConfiguration(SCNetworkServiceGetInterface(service));
+
+       if (isA_CFDictionary(vpn_config)) {
+               CFArrayRef      app_rules = CFDictionaryGetValue(vpn_config, kSCPropNetVPNAppRules);
+               if (isA_CFArray(app_rules)) {
+                       CFIndex app_rule_count = CFArrayGetCount(app_rules);
+                       CFIndex idx;
+                       results = CFArrayCreateMutable(kCFAllocatorDefault, app_rule_count, &kCFTypeArrayCallBacks);
+                       for (idx = 0; idx < app_rule_count; idx++) {
+                               CFDictionaryRef rule = CFArrayGetValueAtIndex(app_rules, idx);
+                               if (isA_CFDictionary(rule)) {
+                                       CFStringRef     rule_ID = CFDictionaryGetValue(rule, kSCValNetVPNAppRuleIdentifier);
+                                       if (isA_CFString(rule_ID)) {
+                                               CFArrayAppendValue(results, CFDictionaryGetValue(rule, kSCValNetVPNAppRuleIdentifier));
+                                       }
+                               }
+                       }
+                       if (CFArrayGetCount(results) == 0) {
+                               CFRelease(results);
+                               results = NULL;
+                       }
+               }
+       }
+
+       if (results == NULL) {
+               _SCErrorSet(kSCStatusOK);
+       }
+
+       return results;
+}
+
+
+Boolean
+VPNServiceSetAppRule(VPNServiceRef service, CFStringRef ruleIdentifier, CFDictionaryRef ruleSettings)
+{
+       CFArrayRef                              accounts;
+       CFArrayRef                              app_rules;
+       CFArrayRef                              executables;
+       CFIndex                                 existing_idx            = -1;
+       CFArrayRef                              match_domains;
+       CFMutableArrayRef               new_app_rules;
+       CFMutableDictionaryRef  new_settings;
+       CFMutableDictionaryRef  new_vpn_config;
+       CFDictionaryRef                 vpn_config;
+
+       /* Basic parameter validation */
+
+       if (!isA_VPNService(service) || !isA_CFString(ruleIdentifier)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return FALSE;
+       }
+
+       if (!validate_app_rule(ruleSettings)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return FALSE;
+       }
+
+       executables = CFDictionaryGetValue(ruleSettings, kSCValNetVPNAppRuleExecutableMatch);
+       match_domains = CFDictionaryGetValue(ruleSettings, kSCValNetVPNAppRuleDNSDomainMatch);
+       accounts = CFDictionaryGetValue(ruleSettings, kSCValNetVPNAppRuleAccountIdentifierMatch);
+
+       /* Set the new rule config, replacing any existing rule */
+
+       vpn_config = SCNetworkInterfaceGetConfiguration(SCNetworkServiceGetInterface(service));
+       if (isA_CFDictionary(vpn_config)) {
+               existing_idx = find_app_rule(vpn_config, ruleIdentifier);
+               new_vpn_config = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, vpn_config);
+       } else {
+               new_vpn_config = CFDictionaryCreateMutable(kCFAllocatorDefault,
+                                                                                                  0,
+                                                                                                  &kCFTypeDictionaryKeyCallBacks,
+                                                                                                  &kCFTypeDictionaryValueCallBacks);
+       }
+
+       app_rules = CFDictionaryGetValue(new_vpn_config, kSCPropNetVPNAppRules);
+       if (isA_CFArray(app_rules)) {
+               new_app_rules = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, app_rules);
+       } else {
+               new_app_rules = CFArrayCreateMutable(kCFAllocatorDefault,
+                                                                                    0,
+                                                                                    &kCFTypeArrayCallBacks);
+       }
+
+       new_settings = CFDictionaryCreateMutable(kCFAllocatorDefault,
+                                                                                        0,
+                                                                                        &kCFTypeDictionaryKeyCallBacks,
+                                                                                        &kCFTypeDictionaryValueCallBacks);
+
+       CFDictionarySetValue(new_settings, kSCValNetVPNAppRuleIdentifier, ruleIdentifier);
+       if (executables != NULL && CFArrayGetCount(executables) > 0) {
+               CFDictionarySetValue(new_settings, kSCValNetVPNAppRuleExecutableMatch, executables);
+       }
+       if (match_domains != NULL && CFArrayGetCount(match_domains) > 0) {
+               CFDictionarySetValue(new_settings, kSCValNetVPNAppRuleDNSDomainMatch, match_domains);
+       }
+       if (accounts != NULL && CFArrayGetCount(accounts) > 0) {
+               CFDictionarySetValue(new_settings, kSCValNetVPNAppRuleAccountIdentifierMatch, accounts);
+       }
+
+       if (existing_idx >= 0) {
+               CFArraySetValueAtIndex(new_app_rules, existing_idx, new_settings);
+       } else {
+               CFArrayAppendValue(new_app_rules, new_settings);
+       }
+
+       CFDictionarySetValue(new_vpn_config, kSCPropNetVPNAppRules, new_app_rules);
+
+       SCNetworkInterfaceSetConfiguration(SCNetworkServiceGetInterface(service), new_vpn_config);
+
+       CFRelease(new_vpn_config);
+       CFRelease(new_app_rules);
+       CFRelease(new_settings);
+
+       return TRUE;
+}
+
+
+CFDictionaryRef
+VPNServiceCopyAppRule(VPNServiceRef service, CFStringRef ruleIdentifier)
+{
+       CFDictionaryRef vpn_config;
+
+       if (!isA_VPNService(service) || !isA_CFString(ruleIdentifier)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return NULL;
+       }
+
+       vpn_config = SCNetworkInterfaceGetConfiguration(SCNetworkServiceGetInterface(service));
+       if (isA_CFDictionary(vpn_config)) {
+               CFIndex idx = find_app_rule(vpn_config, ruleIdentifier);
+               if (idx >= 0) {
+                       CFArrayRef              app_rules               = CFDictionaryGetValue(vpn_config, kSCPropNetVPNAppRules);
+                       CFDictionaryRef ruleSettings    = CFArrayGetValueAtIndex(app_rules, idx);
+
+                       if (validate_app_rule(ruleSettings)) {
+                               return (CFDictionaryRef)CFRetain(ruleSettings);
+                       } else {
+                               _SCErrorSet(kSCStatusFailed);
+                       }
+               } else {
+                       _SCErrorSet(kSCStatusNoKey);
+               }
+       } else {
+               _SCErrorSet(kSCStatusFailed);
+       }
+
+       return NULL;
+}
+
+
+Boolean
+VPNServiceRemoveAppRule(VPNServiceRef service, CFStringRef ruleIdentifier)
+{
+       CFDictionaryRef vpn_config;
+
+       if (!isA_VPNService(service) || !isA_CFString(ruleIdentifier)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return FALSE;
+       }
+
+       vpn_config = SCNetworkInterfaceGetConfiguration(SCNetworkServiceGetInterface(service));
+       if (isA_CFDictionary(vpn_config)) {
+               CFIndex idx = find_app_rule(vpn_config, ruleIdentifier);
+               if (idx >= 0) {
+                       CFArrayRef                              current_app_rules;
+                       current_app_rules = CFDictionaryGetValue(vpn_config, kSCPropNetVPNAppRules);
+                       if (isA_CFArray(current_app_rules)) {
+                               CFMutableDictionaryRef  new_vpn_config;
+                               CFMutableArrayRef               new_app_rules;
+
+                               new_vpn_config = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, vpn_config);
+                               new_app_rules = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, current_app_rules);
+
+                               CFArrayRemoveValueAtIndex(new_app_rules, idx);
+                               if (CFArrayGetCount(new_app_rules) > 0) {
+                                       CFDictionarySetValue(new_vpn_config, kSCPropNetVPNAppRules, new_app_rules);
+                               } else {
+                                       CFDictionaryRemoveValue(new_vpn_config, kSCPropNetVPNAppRules);
+                               }
+
+                               SCNetworkInterfaceSetConfiguration(SCNetworkServiceGetInterface(service), new_vpn_config);
+
+                               CFRelease(new_vpn_config);
+                               CFRelease(new_app_rules);
+
+                               return TRUE;
+                       } else {
+                               _SCErrorSet(kSCStatusFailed);
+                       }
+               } else {
+                       _SCErrorSet(kSCStatusNoKey);
+               }
+       } else {
+               _SCErrorSet(kSCStatusFailed);
+       }
+
+       return FALSE;
+}
+
index 4e587a2ed67ba9e4914e36ce87ed3c91771ccc12..58acb55566492ca3c3a57fce6e6e7c18a8057c92 100644 (file)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2009-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2009-2013 Apple Inc. All rights reserved.
  */
 
index 4e587a2ed67ba9e4914e36ce87ed3c91771ccc12..58acb55566492ca3c3a57fce6e6e7c18a8057c92 100644 (file)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2009-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2009-2013 Apple Inc. All rights reserved.
  */
 
index 4e587a2ed67ba9e4914e36ce87ed3c91771ccc12..58acb55566492ca3c3a57fce6e6e7c18a8057c92 100644 (file)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2009-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2009-2013 Apple Inc. All rights reserved.
  */
 
index a3a63cadd499440c5eb046117ea36dfe34c22386..fb930198dc5b7213b3e367562424a20641ac97bc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2001, 2003, 2005, 2007 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2003, 2005, 2007, 2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 /*
  * Mach server port name
  */
+#if    !TARGET_IPHONE_SIMULATOR
 #define SCD_SERVER     "com.apple.SystemConfiguration.configd"
+#else  // !TARGET_IPHONE_SIMULATOR
+#define SCD_SERVER_HOST        "com.apple.SystemConfiguration.configd"
+#define SCD_SERVER     "com.apple.SystemConfiguration.configd_sim"
+#endif // !TARGET_IPHONE_SIMULATOR
 
 /*
  * Input arguments: serialized key's, list delimiters, ...
index 9366fe4f0d24b5ca5f51c1ed2fec6031cdb9e8c3..e2c1089786dc6e73cf0bf4e2f882dc6e0e4d712f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2008, 2010-2012 Apple Inc. All rights reserved.
+ * Copyright (c) 2002-2008, 2010-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -37,7 +37,6 @@
 #include "dy_framework.h"
 
 
-
 #pragma mark -
 #pragma mark IOKit.framework APIs
 
@@ -338,6 +337,9 @@ SECURITY_FRAMEWORK_EXTERN(CFTypeRef, kSecMatchLimit)
 SECURITY_FRAMEWORK_EXTERN(CFTypeRef, kSecMatchLimitAll)
 SECURITY_FRAMEWORK_EXTERN(CFTypeRef, kSecMatchSearchList)
 SECURITY_FRAMEWORK_EXTERN(CFTypeRef, kSecReturnRef)
+SECURITY_FRAMEWORK_EXTERN(CFTypeRef, kSecGuestAttributePid)
+SECURITY_FRAMEWORK_EXTERN(CFTypeRef, kSecCodeInfoIdentifier)
+SECURITY_FRAMEWORK_EXTERN(CFTypeRef, kSecCodeInfoUnique)
 
 __private_extern__ OSStatus
 _AuthorizationMakeExternalForm(AuthorizationRef authorization, AuthorizationExternalForm *extForm)
@@ -565,3 +567,4 @@ _SecCertificateCreateWithData(CFAllocatorRef allocator, CFDataRef data)
        return dyfunc ? dyfunc(allocator, data) : NULL;
 }
 
+
index 3cd5bd89cb02940312771b501f9d6cbe84a97ceb..0faee13b5c50a6b0e2f59c3cdd0e22785b3cf607 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2008, 2010-2012 Apple Inc. All rights reserved.
+ * Copyright (c) 2002-2008, 2010-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -204,6 +204,15 @@ CFTypeRef _kSecMatchSearchList();
 CFTypeRef _kSecReturnRef();
 #define kSecReturnRef _kSecReturnRef()
 
+CFTypeRef _kSecGuestAttributePid();
+#define kSecGuestAttributePid _kSecGuestAttributePid()
+
+CFTypeRef _kSecCodeInfoIdentifier();
+#define kSecCodeInfoIdentifier _kSecCodeInfoIdentifier()
+
+CFTypeRef _kSecCodeInfoUnique();
+#define kSecCodeInfoUnique _kSecCodeInfoUnique()
+
 OSStatus
 _AuthorizationMakeExternalForm         (
                                        AuthorizationRef                authorization,
@@ -355,6 +364,8 @@ _SecCertificateCreateWithData               (
                                        );
 #define SecCertificateCreateWithData _SecCertificateCreateWithData
 
+
+
 __END_DECLS
 
 #endif // _DY_FRAMEWORK_H
index 5cff79768517a07f475a0f7cf14175a2807e8377..69114d554a57d54a3c5374ac3de36df7df0676f5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -59,7 +59,7 @@
 
 char copyright_string[] =
 "/*\n"
-" * Copyright (c) 2000-2011 Apple Inc. All rights reserved.\n"
+" * Copyright (c) 2000-2013 Apple Inc. All rights reserved.\n"
 " *\n"
 " * @APPLE_LICENSE_HEADER_START@\n"
 " * \n"
@@ -97,6 +97,10 @@ typedef enum {
        SC_10_5_10_7,   // deprecated in 10.7
        SC_10_1_10_6,   // deprecated in 10.6
        SC_10_2_10_6,   // deprecated in 10.6
+       SC_10_1_10_9,   // deprecated in 10.9
+       SC_10_2_10_9,   // deprecated in 10.9
+       SC_10_3_10_9,   // deprecated in 10.9
+       SC_10_4_10_9,   // deprecated in 10.9
        SC_10_6_IPHONE_2_0,
        SC_10_6_IPHONE_3_0,
        SC_10_7_IPHONE_4_0,
@@ -107,6 +111,9 @@ typedef enum {
        SC_10_6_IPHONE_3_0_PRIVATE,
        SC_10_7_IPHONE_4_0_PRIVATE,
        SC_10_7_IPHONE_5_0_PRIVATE,
+       SC_10_8_IPHONE_6_0_PRIVATE,
+       SC_10_9_IPHONE_6_0_PRIVATE,
+       SC_10_9_IPHONE_7_0_PRIVATE,
        SC_IPHONE_2_0_PRIVATE,
        COMMENT_DEPRECATED,
        GROUP_DEPRECATED,
@@ -141,14 +148,18 @@ typedef enum {
 #define CFARRAY_CFSTRING       "CFArray[CFString]"
 #define CFBOOLEAN              "CFBoolean"
 #define CFDATA                 "CFData"
+#define CFDATE                 "CFDATE"
 #define CFDICTIONARY           "CFDictionary"
 #define CFNUMBER               "CFNumber"
 #define CFNUMBER_BOOL          "CFNumber (0 or 1)"
 #define CFSTRING               "CFString"
 
+#define APP                    "App"
 #define ARP                    "ARP"
 #define ACCESSPOINTNAME                "AccessPointName"
+#define ACCOUNT                        "Account"
 #define ACSP                   "ACSP"                  // Apple Client Server Protocol
+#define ACTION                 "Action"
 #define ACTIVE                 "Active"
 #define ADDRESS                        "Address"
 #define ADDRESSES              "Addresses"
@@ -156,6 +167,8 @@ typedef enum {
 #define AGGRESSIVE             "Aggressive"
 #define AIRPORT                        "AirPort"
 #define ALERT                  "Alert"
+#define ALLOW                  "Allow"
+#define ALLOWED                        "Allowed"
 #define ALLOWNETCREATION       "AllowNetCreation"
 #define ALTERNATE              "Alternate"
 #define ALWAYS                 "Always"
@@ -173,12 +186,14 @@ typedef enum {
 #define BOOTP                  "BOOTP"
 #define        BRIDGE                  "Bridge"
 #define BROADCAST              "Broadcast"
+#define BYPASS                 "Bypass"
 #define CALLWAITINGAUDIBLEALERT        "CallWaitingAudibleAlert"
 #define CAPABILITY             "Capability"
 #define CAPABILITIES           "Capabilities"
 #define CAUSE                  "Cause"
 #define CCP                    "CCP"
 #define CHAP                   "CHAP"
+#define CELLULAR               "Cellular"
 #define CERTIFICATE            "Certificate"
 #define COMM                   "Comm"
 #define COMPATIBLE             "Compatible"
@@ -187,6 +202,7 @@ typedef enum {
 #define COMPRESSIONVJ          "CompressionVJ"
 #define COMPUTERNAME           "ComputerName"
 #define CONFIGMETHOD           "ConfigMethod"
+#define CONNECT                        "Connect"
 #define CONNECTDELAY           "ConnectDelay"
 #define CONNECTION             "Connection"
 #define CONNECTSPEED           "ConnectSpeed"
@@ -194,10 +210,12 @@ typedef enum {
 #define CONSERVATIVE           "Conservative"
 #define CONSOLEUSER            "ConsoleUser"
 #define CONTEXTID              "ContextID"
+#define CREDENTIAL             "Credential"
 #define CURRENTSET             "CurrentSet"
 #define DATACOMPRESSION                "DataCompression"
 #define DEFAULT                        "Default"
 #define DEFAULTZONE            "DefaultZone"
+#define DESIGNATED             "Designated"
 #define DEST                   "Dest"
 #define DESTINATION            "Destination"
 #define DETACHING              "Detaching"
@@ -207,12 +225,15 @@ typedef enum {
 #define DHCPCLIENTID           "DHCPClientID"
 #define DIALMODE               "DialMode"
 #define DIALONDEMAND           "DialOnDemand"
+#define DISCONNECT             "Disconnect"
 #define DISCONNECTONANSWER     "DisconnectOnAnswer"
 #define DISCONNECTONFASTUSERSWITCH     "DisconnectOnFastUserSwitch"
 #define DISCONNECTONIDLE       "DisconnectOnIdle"
 #define DISCONNECTONIDLETIMER  "DisconnectOnIdleTimer"
 #define DISCONNECTONLOGOUT     "DisconnectOnLogout"
 #define DISCONNECTONSLEEP      "DisconnectOnSleep"
+#define DISCONNECTONWAKE       "DisconnectOnWake"
+#define DISCONNECTONWAKETIMER  "DisconnectOnWakeTimer"
 #define DISCONNECTTIME         "DisconnectTime"
 #define DISPLAYTERMINALWINDOW  "DisplayTerminalWindow"
 #define DNS                    "DNS"
@@ -229,10 +250,14 @@ typedef enum {
 #define ENCRYPTION             "Encryption"
 #define ERRORCORRECTION                "ErrorCorrection"
 #define ETHERNET               "Ethernet"
+#define EVALUATE               "Evaluate"
 #define EXCEPTIONSLIST         "ExceptionsList"
 #define EXCLUDED               "Excluded"
 #define EXCLUDESIMPLEHOSTNAMES "ExcludeSimpleHostnames"
+#define EXECUTABLE             "Executable"
+#define EXTERNAL               "External"
 #define FAILOVER               "Failover"
+#define        FALLBACK                "FallBack"
 #define FILE                   "File"
 #define FIREWIRE               "FireWire"
 #define FIRST                  "First"
@@ -250,12 +275,16 @@ typedef enum {
 #define HTTP                   "HTTP"
 #define HTTPS                  "HTTPS"
 #define HYBRID                 "Hybrid"
+#define IDENTIFIER             "Identifier"
 #define IDLEREMINDER           "IdleReminder"
 #define IDLEREMINDERTIMER      "IdleReminderTimer"
+#define IFNEEDED               "IfNeeded"
+#define IGNORE                 "Ignore"
 #define IGNOREDIALTONE         "IgnoreDialTone"
 #define IGNORELINKSTATUS       "IgnoreLinkStatus"
 #define INACTIVE               "Inactive"
 #define INCLUDED               "Included"
+#define        INFO                    "Info"
 #define INFORM                 "INFORM"
 #define INTERFACE              "Interface"
 #define INTERFACENAME          "InterfaceName"
@@ -272,8 +301,10 @@ typedef enum {
 #define KEYID                  "KeyID"
 #define L2TP                   "L2TP"
 #define LAST                   "Last"
+#define LAYER                  "Layer"
 #define LCP                    "LCP"
 #define LINK                   "Link"
+#define LINKISSUES             "LinkIssues"
 #define LINKLOCAL              "LinkLocal"
 #define LINKQUALITY            "LinkQuality"
 #define LOCALCERTIFICATE       "LocalCertificate"
@@ -291,6 +322,7 @@ typedef enum {
 #define MODEL                  "Model"
 #define MODE                   "Mode"
 #define MODEM                  "Modem"
+#define MODULEID               "ModuleID"
 #define MPPE40                 "MPPE40"
 #define MPPE128                        "MPPE128"
 #define MRU                    "MRU"
@@ -305,6 +337,7 @@ typedef enum {
 #define NETWORKRANGE           "NetworkRange"
 #define NETWORKSERVICES                "NetworkServices"
 #define NEVER                  "Never"
+#define NO                     "No"
 #define NODE                   "Node"
 #define NODEID                 "NodeID"
 #define NOTE                   "Note"
@@ -315,6 +348,7 @@ typedef enum {
 #define ORDERS                 "Orders"
 #define OVERRIDEPRIMARY                "OverridePrimary"
 #define PAP                    "PAP"
+#define PARAMETERS             "Parameters"
 #define PASSIVE                        "Passive"
 #define PASSWORD               "Password"
 #define PEER                   "Peer"
@@ -334,6 +368,7 @@ typedef enum {
 #define PRIMARYRANK            "PrimaryRank"
 #define PRIMARYSERVICE         "PrimaryService"
 #define PRIORITY               "Priority"
+#define PROBE                  "Probe"
 #define PROMPT                 "Prompt"
 #define PROTOCOL               "Protocol"
 #define PROXIES                        "Proxies"
@@ -350,6 +385,8 @@ typedef enum {
 #define REMINDER               "Reminder"
 #define REMINDERTIME           "ReminderTime"
 #define REMOTEADDRESS          "RemoteAddress"
+#define REQUIRED               "Required"
+#define REQUIREMENT            "Requirement"
 #define RESOLVED               "Resolved"
 #define RETRYCONNECTTIME       "RetryConnectTime"
 #define ROOTSEPARATOR          "RootSeparator"
@@ -358,6 +395,8 @@ typedef enum {
 #define ROUTES                 "Routes"
 #define ROUTERADVERTISEMENT    "RouterAdvertisement"
 #define RTSP                   "RTSP"
+#define RULE                   "Rule"
+#define RULES                  "Rules"
 #define RXCSUM                 "RXCSUM"
 #define SAVEPASSWORDS          "SavePasswords"
 #define SCOPE                  "Scope"
@@ -368,17 +407,21 @@ typedef enum {
 #define SEEDROUTER             "SeedRouter"
 #define SEEDZONES              "SeedZones"
 #define SERVER                 "Server"
+#define SERVERS                        "Servers"
 #define SERVICE                        "Service"
+#define SERVICES               "Services"
 #define SERVICEIDS             "ServiceIDs"
 #define SESSIONTIMER           "SessionTimer"
 #define SETS                   "Sets"
 #define SETUP                  "Setup"
 #define        SHAREDSECRET            "SharedSecret"
+#define SIGNING                        "Signing"
 #define SMB                    "SMB"
 #define SOCKS                  "SOCKS"
 #define SORTLIST               "SortList"
 #define SPEAKER                        "Speaker"
 #define SPEED                  "Speed"
+#define SSID                   "SSID"
 #define STATE                  "State"
 #define STATUS                 "Status"
 #define STF                    "6to4"
@@ -388,11 +431,13 @@ typedef enum {
 #define SUBTYPE                        "SubType"
 #define SUPPLEMENTAL           "Supplemental"
 #define SUPPORTSMODEMONHOLD    "SupportsModemOnHold"
+#define SUSPENDED              "Suspended"
 #define SYSTEM                 "System"
 #define TAG                    "Tag"
 #define TAGS                   "Tags"
 #define TERMINALSCRIPT         "TerminalScript"
 #define TIMEOUT                        "Timeout"
+#define TIMESTAMP              "TimeStamp"
 #define TOKEN                  "Token"
 #define TRANSMITACCM           "TransmitACCM"
 #define TRANSPORT              "Transport"
@@ -415,6 +460,7 @@ typedef enum {
 #define VLAN_MTU               "VLAN_MTU"
 #define        VPN                     "VPN"
 #define WAITFORDIALTONE                "WaitForDialTone"
+#define WIFI                   "WiFi"
 #define WINS                   "WINS"
 #define WORKGROUP              "Workgroup"
 #define XAUTH                  "XAuth"
@@ -505,7 +551,9 @@ static schemaDefinition names[] = {
 
   { GROUP_PRIVATE, NETENT, "Network Entity Keys", NULL, NULL },
 
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETENT, APP LAYER, NULL, CFDICTIONARY},
     { SC_10_5_PRIVATE, NETENT, EAPOL, NULL, CFDICTIONARY },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETENT, LINKISSUES, NULL, CFDICTIONARY},
     { SC_10_7_IPHONE_5_0_PRIVATE, NETENT, LINKQUALITY, NULL, CFDICTIONARY}, 
     { SC_10_7_IPHONE_4_0_PRIVATE, NETENT, LOOPBACK, NULL, CFDICTIONARY },
     { SC_10_6_IPHONE_3_0_PRIVATE, NETENT, ONDEMAND, NULL, CFDICTIONARY },
@@ -525,36 +573,36 @@ static schemaDefinition names[] = {
     { SC_10_5_PRIVATE, NETPROP, IGNORELINKSTATUS, NULL, CFBOOLEAN },
     { COMMENT_PRIVATE, "", NULL, NULL, NULL }, 
        
-  { GROUP, NETPROP AIRPORT, KEY_PREFIX COMP NETWORK INTERFACE " Properties", NULL, NULL },
+  { GROUP, NETPROP INTERFACES, KEY_PREFIX COMP NETWORK INTERFACE " Properties", NULL, NULL },
 
     { SC_10_2, NETPROP, INTERFACES, NULL, CFARRAY_CFSTRING },
     { COMMENT, "", NULL, NULL, NULL },
 
-  { GROUP, NETPROP AIRPORT, KEY_PREFIX COMP NETWORK HOSTNAMES " Properties", NULL, NULL },
+  { GROUP, NETPROP LOCALHOSTNAME, KEY_PREFIX COMP NETWORK HOSTNAMES " Properties", NULL, NULL },
 
     { SC_10_2, NETPROP, LOCALHOSTNAME, NULL, CFSTRING },
     { COMMENT, "", NULL, NULL, NULL },
 
-  { GROUP, NETPROP AIRPORT, KEY_PREFIX NETENT AIRPORT " (Hardware) Entity Keys", NULL, NULL },
+  { GROUP_DEPRECATED, NETPROP AIRPORT, KEY_PREFIX NETENT AIRPORT " (Hardware) Entity Keys", NULL, NULL },
 
-    { SC_10_2, NETPROP AIRPORT, ALLOWNETCREATION, NULL, CFNUMBER_BOOL },
-    { SC_10_1, NETPROP AIRPORT, AUTH PASSWORD, NULL, CFDATA },
-    { SC_10_1, NETPROP AIRPORT, AUTH PASSWORD ENCRYPTION, NULL, CFSTRING },
-    { SC_10_2, NETPROP AIRPORT, JOIN MODE, NULL, CFSTRING },
-    { SC_10_1, NETPROP AIRPORT, POWER ENABLED, NULL, CFNUMBER_BOOL },
-    { SC_10_1, NETPROP AIRPORT, PREFERRED NETWORK, NULL, CFSTRING },
-    { SC_10_2, NETPROP AIRPORT, SAVEPASSWORDS, NULL, CFNUMBER_BOOL },
-    { COMMENT, "", NULL, NULL, NULL },
-    { COMMENT, "--- " KEY_PREFIX NETPROP AIRPORT JOIN MODE " values ---", NULL, NULL, NULL },
-    { SC_10_3, NETVAL AIRPORT JOIN MODE, AUTOMATIC, NULL, NULL },
-    { SC_10_2, NETVAL AIRPORT JOIN MODE, PREFERRED, NULL, NULL },
-    { SC_10_4, NETVAL AIRPORT JOIN MODE, RANKED, NULL, NULL },
-    { SC_10_2, NETVAL AIRPORT JOIN MODE, RECENT, NULL, NULL },
-    { SC_10_2, NETVAL AIRPORT JOIN MODE, STRONGEST, NULL, NULL },
-    { COMMENT, "", NULL, NULL, NULL },
-    { COMMENT, "--- " KEY_PREFIX NETPROP AIRPORT PASSWORD ENCRYPTION " values ---", NULL, NULL, NULL },
-    { SC_10_3, NETVAL AIRPORT AUTH PASSWORD ENCRYPTION, KEYCHAIN, NULL, NULL },
-    { COMMENT, "", NULL, NULL, NULL },
+    { SC_10_2_10_9, NETPROP AIRPORT, ALLOWNETCREATION, NULL, CFNUMBER_BOOL },
+    { SC_10_1_10_9, NETPROP AIRPORT, AUTH PASSWORD, NULL, CFDATA },
+    { SC_10_1_10_9, NETPROP AIRPORT, AUTH PASSWORD ENCRYPTION, NULL, CFSTRING },
+    { SC_10_2_10_9, NETPROP AIRPORT, JOIN MODE, NULL, CFSTRING },
+    { SC_10_1_10_9, NETPROP AIRPORT, POWER ENABLED, NULL, CFNUMBER_BOOL },
+    { SC_10_1_10_9, NETPROP AIRPORT, PREFERRED NETWORK, NULL, CFSTRING },
+    { SC_10_2_10_9, NETPROP AIRPORT, SAVEPASSWORDS, NULL, CFNUMBER_BOOL },
+    { COMMENT_DEPRECATED, "", NULL, NULL, NULL },
+    { COMMENT_DEPRECATED, "--- " KEY_PREFIX NETPROP AIRPORT JOIN MODE " values ---", NULL, NULL, NULL },
+    { SC_10_3_10_9, NETVAL AIRPORT JOIN MODE, AUTOMATIC, NULL, NULL },
+    { SC_10_2_10_9, NETVAL AIRPORT JOIN MODE, PREFERRED, NULL, NULL },
+    { SC_10_4_10_9, NETVAL AIRPORT JOIN MODE, RANKED, NULL, NULL },
+    { SC_10_2_10_9, NETVAL AIRPORT JOIN MODE, RECENT, NULL, NULL },
+    { SC_10_2_10_9, NETVAL AIRPORT JOIN MODE, STRONGEST, NULL, NULL },
+    { COMMENT_DEPRECATED, "", NULL, NULL, NULL },
+    { COMMENT_DEPRECATED, "--- " KEY_PREFIX NETPROP AIRPORT PASSWORD ENCRYPTION " values ---", NULL, NULL, NULL },
+    { SC_10_3_10_9, NETVAL AIRPORT AUTH PASSWORD ENCRYPTION, KEYCHAIN, NULL, NULL },
+    { COMMENT_DEPRECATED, "", NULL, NULL, NULL },
 
   { GROUP_DEPRECATED, NETPROP APPLETALK, KEY_PREFIX NETENT APPLETALK " Entity Keys", NULL, NULL },
 
@@ -591,6 +639,12 @@ static schemaDefinition names[] = {
     { SC_10_4, NETPROP DNS, SUPPLEMENTAL MATCH ORDERS, NULL, CFARRAY_CFNUMBER},
     { COMMENT, "", NULL, NULL, NULL },
 
+  { GROUP_PRIVATE, NETPROP DNS, KEY_PREFIX NETENT DNS " Entity Keys", NULL, NULL },
+
+       { SC_10_9_IPHONE_7_0_PRIVATE, NETPROP DNS, SERVICE IDENTIFIER, NULL, CFNUMBER },
+       { SC_10_9_IPHONE_7_0_PRIVATE, NETPROP DNS, SUPPLEMENTAL MATCH DOMAINS NO SEARCH, NULL, CFNUMBER_BOOL},
+    { COMMENT_PRIVATE, "", NULL, NULL, NULL },
+
   { GROUP, NETPROP ETHERNET, KEY_PREFIX NETENT ETHERNET " (Hardware) Entity Keys", NULL, NULL },
 
     { SC_10_2, NETPROP ETHERNET, MEDIA SUBTYPE, NULL, CFSTRING },
@@ -661,6 +715,8 @@ static schemaDefinition names[] = {
     { SC_10_6_IPHONE_2_0, NETPROP IPSEC, XAUTH NAME, NULL, CFSTRING },
     { SC_10_6_IPHONE_2_0, NETPROP IPSEC, XAUTH PASSWORD, NULL, CFSTRING },
     { SC_10_6_IPHONE_2_0, NETPROP IPSEC, XAUTH PASSWORD ENCRYPTION, NULL, CFSTRING },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETPROP IPSEC, DISCONNECTONWAKE, NULL, CFNUMBER_BOOL },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETPROP IPSEC, DISCONNECTONWAKETIMER, NULL, CFNUMBER },
     { COMMENT, "", NULL, NULL, NULL },
     { COMMENT, "--- " KEY_PREFIX NETPROP IPSEC AUTHENTICATIONMETHOD " values ---", NULL, NULL, NULL },
     { SC_10_5, NETVAL IPSEC AUTHENTICATIONMETHOD, SHAREDSECRET, NULL, NULL },
@@ -765,6 +821,13 @@ static schemaDefinition names[] = {
     { SC_10_2, NETPROP LINK, DETACHING, NULL, CFBOOLEAN },
     { COMMENT, "", NULL, NULL, NULL },
 
+  { GROUP_PRIVATE, NETPROP LINK, KEY_PREFIX NETENT LINKISSUES " Entity Keys", NULL, NULL },
+
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETPROP LINKISSUES, MODULEID, NULL, CFDATA },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETPROP LINKISSUES, INFO, NULL, CFDATA },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETPROP LINKISSUES, TIMESTAMP, NULL, CFDATE },
+    { COMMENT_PRIVATE, "", NULL, NULL, NULL },
+
   { GROUP_PRIVATE, NETPROP LINK, KEY_PREFIX NETENT LINKQUALITY " Entity Keys", NULL, NULL },
 
     { SC_10_7_IPHONE_5_0_PRIVATE, NETPROP, LINKQUALITY, NULL, CFNUMBER},
@@ -827,6 +890,8 @@ static schemaDefinition names[] = {
     { SC_10_1, NETPROP PPP, DISCONNECTONIDLETIMER, NULL, CFNUMBER },
     { SC_10_1, NETPROP PPP, DISCONNECTONLOGOUT, NULL, CFNUMBER_BOOL },
     { SC_10_2, NETPROP PPP, DISCONNECTONSLEEP, NULL, CFNUMBER_BOOL },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETPROP PPP, DISCONNECTONWAKE, NULL, CFNUMBER_BOOL },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETPROP PPP, DISCONNECTONWAKETIMER, NULL, CFNUMBER },
     { SC_10_3, NETPROP PPP, DISCONNECTTIME, NULL, CFNUMBER },
     { SC_10_1, NETPROP PPP, IDLEREMINDERTIMER, NULL, CFNUMBER },
     { SC_10_1, NETPROP PPP, IDLEREMINDER, NULL, CFNUMBER_BOOL },
@@ -982,10 +1047,13 @@ static schemaDefinition names[] = {
 
   { GROUP_PRIVATE, NETPROP PROXIES, KEY_PREFIX NETENT PROXIES " Entity Keys", NULL, NULL },
 
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETPROP PROXIES, BYPASS ALLOWED, NULL, CFNUMBER_BOOL },
+    { SC_10_9_IPHONE_6_0_PRIVATE, NETPROP PROXIES, FALLBACK ALLOWED, NULL, CFNUMBER_BOOL },
     { SC_10_7_IPHONE_5_0_PRIVATE, NETPROP PROXIES, SUPPLEMENTAL MATCH DOMAINS, NULL, CFARRAY_CFSTRING},
     { SC_10_7_IPHONE_5_0_PRIVATE, NETPROP PROXIES, SUPPLEMENTAL MATCH ORDERS, NULL, CFARRAY_CFNUMBER},
     { COMMENT_PRIVATE, "", NULL, NULL, NULL },
     { SC_10_7_IPHONE_5_0_PRIVATE, NETPROP PROXIES, SCOPED, "__SCOPED__", CFDICTIONARY},
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETPROP PROXIES, SERVICES, "__SERVICES__", CFDICTIONARY},
     { SC_10_7_IPHONE_5_0_PRIVATE, NETPROP PROXIES, SUPPLEMENTAL, "__SUPPLEMENTAL__", CFARRAY_CFDICTIONARY},
     { SC_10_7_IPHONE_5_0_PRIVATE, NETPROP PROXIES, SUPPLEMENTAL MATCH DOMAIN, "__MATCH_DOMAIN__", CFSTRING},
     { COMMENT_PRIVATE, "", NULL, NULL, NULL },
@@ -1020,9 +1088,12 @@ static schemaDefinition names[] = {
 
   { GROUP_PRIVATE, NETPROP VPN, KEY_PREFIX NETENT VPN " Entity Keys", NULL, NULL },
 
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETPROP VPN, APP RULES, NULL, CFARRAY_CFDICTIONARY },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETPROP VPN, AUTH CREDENTIAL PASSWORD, NULL, CFSTRING },
     { SC_10_7_IPHONE_4_0_PRIVATE, NETPROP VPN, AUTH NAME, NULL, CFSTRING },
     { SC_10_7_IPHONE_4_0_PRIVATE, NETPROP VPN, AUTH PASSWORD, NULL, CFSTRING },
     { SC_10_7_IPHONE_4_0_PRIVATE, NETPROP VPN, AUTH PASSWORD ENCRYPTION, NULL, CFSTRING },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETPROP VPN, AUTH PASSWORD PLUGIN TYPE, NULL, CFSTRING },
     { SC_10_7_IPHONE_4_0_PRIVATE, NETPROP VPN, AUTHENTICATIONMETHOD, NULL, CFSTRING },
     { SC_10_7_IPHONE_4_0_PRIVATE, NETPROP VPN, CONNECTTIME, NULL, CFSTRING },
     { SC_10_7_IPHONE_4_0_PRIVATE, NETPROP VPN, DISCONNECTONFASTUSERSWITCH, NULL, CFNUMBER_BOOL },
@@ -1030,25 +1101,76 @@ static schemaDefinition names[] = {
     { SC_10_7_IPHONE_4_0_PRIVATE, NETPROP VPN, DISCONNECTONIDLETIMER, NULL, CFNUMBER },
     { SC_10_7_IPHONE_4_0_PRIVATE, NETPROP VPN, DISCONNECTONLOGOUT, NULL, CFNUMBER_BOOL },
     { SC_10_7_IPHONE_4_0_PRIVATE, NETPROP VPN, DISCONNECTONSLEEP, NULL, CFNUMBER_BOOL },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETPROP VPN, DISCONNECTONWAKE, NULL, CFNUMBER_BOOL },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETPROP VPN, DISCONNECTONWAKETIMER, NULL, CFNUMBER },
     { SC_10_7_IPHONE_4_0_PRIVATE, NETPROP VPN, LOCALCERTIFICATE, NULL, CFDATA },
     { SC_10_7_IPHONE_4_0_PRIVATE, NETPROP VPN, LOGFILE, NULL, CFSTRING },
     { SC_10_7_IPHONE_4_0_PRIVATE, NETPROP VPN, MTU, NULL, CFNUMBER },
     { SC_10_7_IPHONE_4_0_PRIVATE, NETPROP VPN, ONDEMAND ENABLED, NULL, CFNUMBER_BOOL },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETPROP VPN, ONDEMAND MATCH APP ENABLED, NULL, CFBOOLEAN },
     { SC_10_7_IPHONE_4_0_PRIVATE, NETPROP VPN, ONDEMAND MATCH DOMAINS ALWAYS, NULL, CFARRAY_CFSTRING },
     { SC_10_7_IPHONE_4_0_PRIVATE, NETPROP VPN, ONDEMAND MATCH DOMAINS ONRETRY, NULL, CFARRAY_CFSTRING },
     { SC_10_7_IPHONE_4_0_PRIVATE, NETPROP VPN, ONDEMAND MATCH DOMAINS NEVER, NULL, CFARRAY_CFSTRING },
+    { SC_10_8_IPHONE_6_0_PRIVATE, NETPROP VPN, ONDEMAND RULES, NULL, CFARRAY_CFDICTIONARY },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETPROP VPN, ONDEMAND SUSPENDED, NULL, CFNUMBER },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETPROP VPN, PLUGIN CAPABILITY, NULL, CFSTRING },
     { SC_10_7_IPHONE_4_0_PRIVATE, NETPROP VPN, REMOTEADDRESS, NULL, CFSTRING },
     { SC_10_7_IPHONE_4_0_PRIVATE, NETPROP VPN, STATUS, NULL, CFNUMBER },
     { SC_10_7_IPHONE_4_0_PRIVATE, NETPROP VPN, VERBOSELOGGING, NULL, CFNUMBER_BOOL },
     { COMMENT_PRIVATE, "", NULL, NULL, NULL },
+    { COMMENT_PRIVATE, "--- " KEY_PREFIX NETPROP VPN APP RULES  " [CFDictionary] keys ---", NULL, NULL, NULL },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETVAL VPN APP RULE, ACCOUNT IDENTIFIER MATCH, NULL, CFARRAY_CFSTRING },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETVAL VPN APP RULE, DNS DOMAIN MATCH, NULL, CFARRAY_CFSTRING },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETVAL VPN APP RULE, EXECUTABLE MATCH, NULL, CFARRAY_CFDICTIONARY },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETVAL VPN APP RULE, IDENTIFIER, NULL, CFSTRING },
+    { COMMENT_PRIVATE, "", NULL, NULL, NULL },
+    { COMMENT_PRIVATE, "--- " KEY_PREFIX NETVAL VPN APP RULE EXECUTABLE MATCH " [CFDictionary] keys ---", NULL, NULL, NULL },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETVAL VPN APP RULE EXECUTABLE, DESIGNATED REQUIREMENT, NULL, CFSTRING },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETVAL VPN APP RULE EXECUTABLE, SIGNING IDENTIFIER, NULL, CFSTRING },
+    { COMMENT_PRIVATE, "", NULL, NULL, NULL },
     { COMMENT_PRIVATE, "--- " KEY_PREFIX NETPROP VPN AUTHENTICATIONMETHOD " values ---", NULL, NULL, NULL },
     { SC_10_7_IPHONE_4_0_PRIVATE, NETVAL VPN AUTHENTICATIONMETHOD, PASSWORD, NULL, NULL },
     { SC_10_7_IPHONE_4_0_PRIVATE, NETVAL VPN AUTHENTICATIONMETHOD, CERTIFICATE, NULL, NULL },
     { COMMENT_PRIVATE, "", NULL, NULL, NULL },
     { COMMENT_PRIVATE, "--- " KEY_PREFIX NETPROP VPN AUTH PASSWORD ENCRYPTION " values ---", NULL, NULL, NULL },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETVAL VPN AUTH PASSWORD ENCRYPTION, EXTERNAL, NULL, NULL },
     { SC_10_7_IPHONE_4_0_PRIVATE, NETVAL VPN AUTH PASSWORD ENCRYPTION, KEYCHAIN, NULL, NULL },
     { SC_10_7_IPHONE_4_0_PRIVATE, NETVAL VPN AUTH PASSWORD ENCRYPTION, PROMPT, NULL, NULL },
     { COMMENT_PRIVATE, "", NULL, NULL, NULL },
+    { COMMENT_PRIVATE, "--- " KEY_PREFIX NETPROP VPN ONDEMAND RULES " [CFDictionary] keys ---", NULL, NULL, NULL },
+    { SC_10_8_IPHONE_6_0_PRIVATE, NETPROP VPN ONDEMAND RULE, ACTION, NULL, CFSTRING },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETPROP VPN ONDEMAND RULE, ACTION PARAMETERS, NULL, CFARRAY_CFDICTIONARY },
+    { SC_10_8_IPHONE_6_0_PRIVATE, NETPROP VPN ONDEMAND RULE, DNS DOMAIN MATCH, NULL, CFARRAY_CFSTRING },
+    { SC_10_8_IPHONE_6_0_PRIVATE, NETPROP VPN ONDEMAND RULE, DNS SERVER ADDRESS MATCH, NULL, CFARRAY_CFSTRING },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETPROP VPN ONDEMAND RULE, SSID MATCH, NULL, CFARRAY_CFSTRING },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETPROP VPN ONDEMAND RULE, INTERFACE TYPE MATCH, NULL, CFSTRING },
+    { SC_10_8_IPHONE_6_0_PRIVATE, NETPROP VPN ONDEMAND RULE, URLSTRING PROBE, NULL, CFSTRING },
+    { COMMENT_PRIVATE, "", NULL, NULL, NULL },
+    { COMMENT_PRIVATE, "--- " KEY_PREFIX NETPROP VPN ONDEMAND RULE ACTION " values ---", NULL, NULL, NULL },
+    { SC_10_8_IPHONE_6_0_PRIVATE, NETVAL VPN ONDEMAND RULE ACTION, ALLOW, NULL, NULL },
+    { SC_10_8_IPHONE_6_0_PRIVATE, NETVAL VPN ONDEMAND RULE ACTION, IGNORE, NULL, NULL },
+    { SC_10_8_IPHONE_6_0_PRIVATE, NETVAL VPN ONDEMAND RULE ACTION, CONNECT, NULL, NULL },
+    { SC_10_8_IPHONE_6_0_PRIVATE, NETVAL VPN ONDEMAND RULE ACTION, DISCONNECT, NULL, NULL },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETVAL VPN ONDEMAND RULE ACTION, EVALUATE CONNECTION, NULL, NULL },
+    { COMMENT_PRIVATE, "", NULL, NULL, NULL },
+    { COMMENT_PRIVATE, "--- " KEY_PREFIX NETPROP VPN ONDEMAND RULE ACTION PARAMETERS " [CFDictionary] keys ---", NULL, NULL, NULL },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETPROP VPN ONDEMAND RULE ACTION PARAMETERS, DOMAIN ACTION, NULL, CFSTRING },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETPROP VPN ONDEMAND RULE ACTION PARAMETERS, DOMAINS, NULL, CFARRAY_CFSTRING },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETPROP VPN ONDEMAND RULE ACTION PARAMETERS, REQUIRED DNS SERVERS, NULL, CFARRAY_CFSTRING },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETPROP VPN ONDEMAND RULE ACTION PARAMETERS, REQUIRED URLSTRING PROBE, NULL, CFSTRING },
+    { COMMENT_PRIVATE, "", NULL, NULL, NULL },
+    { COMMENT_PRIVATE, "--- " KEY_PREFIX NETPROP VPN ONDEMAND RULE ACTION PARAMETERS DOMAIN ACTION " values ---", NULL, NULL, NULL },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETVAL VPN ONDEMAND RULE ACTION PARAMETERS DOMAIN ACTION, CONNECT IFNEEDED, NULL, NULL },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETVAL VPN ONDEMAND RULE ACTION PARAMETERS DOMAIN ACTION, NEVER CONNECT, NULL, NULL },
+    { COMMENT_PRIVATE, "", NULL, NULL, NULL },
+    { COMMENT_PRIVATE, "--- " KEY_PREFIX NETPROP VPN ONDEMAND RULE INTERFACE TYPE MATCH " values ---", NULL, NULL, NULL },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETVAL VPN ONDEMAND RULE INTERFACE TYPE MATCH, ETHERNET, NULL, NULL },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETVAL VPN ONDEMAND RULE INTERFACE TYPE MATCH, WIFI, NULL, NULL },
+    { COMMENT_PRIVATE, "", NULL, NULL, NULL },
+    { COMMENT_PRIVATE, "--- " KEY_PREFIX NETPROP VPN PLUGIN CAPABILITY " values ---", NULL, NULL, NULL },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETVAL VPN PLUGIN CAPABILITY, AUTH, NULL, NULL },
+    { SC_10_9_IPHONE_7_0_PRIVATE, NETVAL VPN PLUGIN CAPABILITY, CONNECT, NULL, NULL },
+    { COMMENT_PRIVATE, "", NULL, NULL, NULL },
 
   { GROUP, USERSENT CONSOLEUSER, KEY_PREFIX COMP USERS " Entity Keys", NULL, NULL },
 
@@ -1228,6 +1350,18 @@ print_headerdoc(schemaDefinition *def)
            case SC_10_2_10_6:
                printf("  @availability Introduced in Mac OS X 10.2, but later deprecated in Mac OS X 10.6.\n");
                break;
+           case SC_10_1_10_9:
+               printf("  @availability Introduced in Mac OS X 10.1, but later deprecated in Mac OS X 10.9.\n");
+               break;
+           case SC_10_2_10_9:
+               printf("  @availability Introduced in Mac OS X 10.2, but later deprecated in Mac OS X 10.9.\n");
+               break;
+           case SC_10_3_10_9:
+               printf("  @availability Introduced in Mac OS X 10.3, but later deprecated in Mac OS X 10.9.\n");
+               break;
+           case SC_10_4_10_9:
+               printf("  @availability Introduced in Mac OS X 10.4, but later deprecated in Mac OS X 10.9.\n");
+               break;
            case SC_10_6_IPHONE_2_0:
            case SC_10_6_IPHONE_2_0_PRIVATE:
                printf("  @availability Introduced in Mac OS X 10.6.\n");
@@ -1241,6 +1375,13 @@ print_headerdoc(schemaDefinition *def)
            case SC_10_7_IPHONE_5_0_PRIVATE:
                printf("  @availability Introduced in Mac OS X 10.7.\n");
                break;
+           case SC_10_8_IPHONE_6_0_PRIVATE:
+               printf("  @availability Introduced in Mac OS X 10.8.\n");
+               break;
+           case SC_10_9_IPHONE_6_0_PRIVATE:
+           case SC_10_9_IPHONE_7_0_PRIVATE:
+               printf("  @availability Introduced in Mac OS X 10.9.\n");
+               break;
            case SC_IPHONE_2_0_PRIVATE:
                printf("  @availability Introduced in iPhone OS 2.0.\n");
                break;
@@ -1301,6 +1442,18 @@ print_hfile(schemaDefinition *def)
            case SC_10_2_10_6:
                printf("  " SC_SCHEMA_DECLARATION "(%s, __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2,__MAC_10_6,__IPHONE_NA,__IPHONE_NA))\n", kbuf);
                break;
+           case SC_10_1_10_9:
+               printf("  " SC_SCHEMA_DECLARATION "(%s, __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_1,__MAC_10_9,__IPHONE_2_0/*SPI*/,__IPHONE_FUTURE/*SPI*/))\n", kbuf);
+               break;
+           case SC_10_2_10_9:
+               printf("  " SC_SCHEMA_DECLARATION "(%s, __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2,__MAC_10_9,__IPHONE_2_0/*SPI*/,__IPHONE_FUTURE/*SPI*/))\n", kbuf);
+               break;
+           case SC_10_3_10_9:
+               printf("  " SC_SCHEMA_DECLARATION "(%s, __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_3,__MAC_10_9,__IPHONE_2_0/*SPI*/,__IPHONE_FUTURE/*SPI*/))\n", kbuf);
+               break;
+           case SC_10_4_10_9:
+               printf("  " SC_SCHEMA_DECLARATION "(%s, __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4,__MAC_10_9,__IPHONE_2_0/*SPI*/,__IPHONE_FUTURE/*SPI*/))\n", kbuf);
+               break;
            case SC_10_6_IPHONE_2_0:
            case SC_10_6_IPHONE_2_0_PRIVATE:
                printf("  " SC_SCHEMA_DECLARATION "(%s, __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_2_0/*SPI*/))\n", kbuf);
@@ -1316,6 +1469,15 @@ print_hfile(schemaDefinition *def)
            case SC_10_7_IPHONE_5_0_PRIVATE:
                printf("  " SC_SCHEMA_DECLARATION "(%s, __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_5_0/*SPI*/))\n", kbuf);
                break;
+           case SC_10_8_IPHONE_6_0_PRIVATE:
+               printf("  " SC_SCHEMA_DECLARATION "(%s, __OSX_AVAILABLE_STARTING(__MAC_10_8,__IPHONE_6_0/*SPI*/))\n", kbuf);
+               break;
+           case SC_10_9_IPHONE_6_0_PRIVATE:
+               printf("  " SC_SCHEMA_DECLARATION "(%s, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0/*SPI*/))\n", kbuf);
+               break;
+           case SC_10_9_IPHONE_7_0_PRIVATE:
+               printf("  " SC_SCHEMA_DECLARATION "(%s, __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/))\n", kbuf);
+               break;
            case SC_IPHONE_2_0_PRIVATE:
                printf("  " SC_SCHEMA_DECLARATION "(%s, __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_2_0/*SPI*/))\n", kbuf);
                break;
@@ -1350,11 +1512,12 @@ dump_names(int type)
            case COMMENT: {
                switch (type) {
                    case gen_comments_e:
-                       if (names[i].prefix)
+                       if (names[i].prefix) {
                            if (strlen(names[i].prefix) > 0)
                                printf(" *   %s\n", names[i].prefix);
                            else
                                printf(" *\n");
+                       }
                        break;
                    default:
                        break;
@@ -1365,11 +1528,12 @@ dump_names(int type)
            case COMMENT_PRIVATE: {
                switch (type) {
                    case gen_comments_private_e:
-                       if (names[i].prefix)
+                       if (names[i].prefix) {
                            if (strlen(names[i].prefix) > 0)
                                printf(" *   %s\n", names[i].prefix);
                            else
                                printf(" *\n");
+                       }
                        break;
                    default:
                        break;
@@ -1484,6 +1648,10 @@ dump_names(int type)
                            case SC_10_1_10_5:
                            case SC_10_1_10_6:
                            case SC_10_2_10_6:
+                           case SC_10_1_10_9:
+                           case SC_10_2_10_9:
+                           case SC_10_3_10_9:
+                           case SC_10_4_10_9:
                                // don't report deprecated keys
                                break;
                            case SC_10_5_PRIVATE:
@@ -1491,6 +1659,9 @@ dump_names(int type)
                            case SC_10_6_IPHONE_3_0_PRIVATE:
                            case SC_10_7_IPHONE_4_0_PRIVATE:
                            case SC_10_7_IPHONE_5_0_PRIVATE:
+                           case SC_10_8_IPHONE_6_0_PRIVATE:
+                           case SC_10_9_IPHONE_6_0_PRIVATE:
+                           case SC_10_9_IPHONE_7_0_PRIVATE:
                            case SC_IPHONE_2_0_PRIVATE:
                                // don't report private definitions
                                break;
@@ -1505,6 +1676,10 @@ dump_names(int type)
                            case SC_10_1_10_5:
                            case SC_10_1_10_6:
                            case SC_10_2_10_6:
+                           case SC_10_1_10_9:
+                           case SC_10_2_10_9:
+                           case SC_10_3_10_9:
+                           case SC_10_4_10_9:
                                // don't report deprecated keys
                                break;
                            case SC_10_5_PRIVATE:
@@ -1512,6 +1687,9 @@ dump_names(int type)
                            case SC_10_6_IPHONE_3_0_PRIVATE:
                            case SC_10_7_IPHONE_4_0_PRIVATE:
                            case SC_10_7_IPHONE_5_0_PRIVATE:
+                           case SC_10_8_IPHONE_6_0_PRIVATE:
+                           case SC_10_9_IPHONE_6_0_PRIVATE:
+                           case SC_10_9_IPHONE_7_0_PRIVATE:
                            case SC_IPHONE_2_0_PRIVATE:
                                print_comment(&names[i]);
                                break;
@@ -1528,6 +1706,9 @@ dump_names(int type)
                            case SC_10_6_IPHONE_3_0_PRIVATE:
                            case SC_10_7_IPHONE_4_0_PRIVATE:
                            case SC_10_7_IPHONE_5_0_PRIVATE:
+                           case SC_10_8_IPHONE_6_0_PRIVATE:
+                           case SC_10_9_IPHONE_6_0_PRIVATE:
+                           case SC_10_9_IPHONE_7_0_PRIVATE:
                            case SC_IPHONE_2_0_PRIVATE:
                                // don't report private definitions
                                break;
@@ -1543,6 +1724,9 @@ dump_names(int type)
                            case SC_10_6_IPHONE_3_0_PRIVATE:
                            case SC_10_7_IPHONE_4_0_PRIVATE:
                            case SC_10_7_IPHONE_5_0_PRIVATE:
+                           case SC_10_8_IPHONE_6_0_PRIVATE:
+                           case SC_10_9_IPHONE_6_0_PRIVATE:
+                           case SC_10_9_IPHONE_7_0_PRIVATE:
                            case SC_IPHONE_2_0_PRIVATE:
                                print_headerdoc(&names[i]);
                                break;
@@ -1559,6 +1743,9 @@ dump_names(int type)
                            case SC_10_6_IPHONE_3_0_PRIVATE:
                            case SC_10_7_IPHONE_4_0_PRIVATE:
                            case SC_10_7_IPHONE_5_0_PRIVATE:
+                           case SC_10_8_IPHONE_6_0_PRIVATE:
+                           case SC_10_9_IPHONE_6_0_PRIVATE:
+                           case SC_10_9_IPHONE_7_0_PRIVATE:
                            case SC_IPHONE_2_0_PRIVATE:
                                break;
                                // don't report private definitions
@@ -1574,6 +1761,9 @@ dump_names(int type)
                            case SC_10_6_IPHONE_3_0_PRIVATE:
                            case SC_10_7_IPHONE_4_0_PRIVATE:
                            case SC_10_7_IPHONE_5_0_PRIVATE:
+                           case SC_10_8_IPHONE_6_0_PRIVATE:
+                           case SC_10_9_IPHONE_6_0_PRIVATE:
+                           case SC_10_9_IPHONE_7_0_PRIVATE:
                            case SC_IPHONE_2_0_PRIVATE:
                                print_hfile(&names[i]);
                                break;
@@ -1707,6 +1897,8 @@ main(int argc, char * argv[])
        printf("#endif\t/* 0 */\n\n\n");
 
        printf("/* -------------------- Schema declarations -------------------- */\n\n");
+
+       
        dump_names(gen_hfile_e);
        printf("\n");
 
index ad83e9cfdebd39691e4f8b3994d3221d65bbb743..01fd485249a2e014765357cef9094eae476c16c5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2012 Apple Inc. All rights reserved.
+ * Copyright (c) 2005-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -45,6 +45,8 @@
 #include "SCHelper_client.h"
 #include "helper_types.h"
 
+#include <libproc_internal.h>
+
 
 #pragma mark -
 #pragma mark SCHelper session managment
@@ -53,6 +55,7 @@
 //
 // entitlement used to control write access to a given "prefsID"
 //
+#define        kSCReadEntitlementName          CFSTR("com.apple.SystemConfiguration.SCPreferences-read-access")
 #define        kSCWriteEntitlementName         CFSTR("com.apple.SystemConfiguration.SCPreferences-write-access")
 
 //
@@ -84,10 +87,13 @@ typedef struct {
        audit_token_t           auditToken;
 
        // write access entitlement associated with this session
+       lazyBoolean             callerReadAccess;
        lazyBoolean             callerWriteAccess;
 
-       // VPN configuration filtering
-       CFArrayRef              vpnFilter;
+       // configuration filtering
+       lazyBoolean             isSetChange;    // only network "set" changes
+       lazyBoolean             isVPNChange;    // only VPN configuration changes
+       CFArrayRef              vpnTypes;
 
        // preferences
        SCPreferencesRef        prefs;
@@ -119,7 +125,7 @@ static pthread_mutex_t      sessions_lock                   = PTHREAD_MUTEX_INITIALIZER;
 #pragma mark Helper session management
 
 
-#if !TARGET_OS_IPHONE
+#if    !TARGET_OS_IPHONE
 static Boolean
  __SCHelperSessionUseEntitlement(SCHelperSessionRef session)
 {
@@ -127,7 +133,7 @@ static Boolean
 
        return sessionPrivate->use_entitlement;
 }
-#endif //!TARGET_OS_IPHONE
+#endif //!TARGET_OS_IPHONE
 
 
 static AuthorizationRef
@@ -145,25 +151,31 @@ __SCHelperSessionSetAuthorization(SCHelperSessionRef session, CFTypeRef authoriz
        Boolean                         ok              = TRUE;
        SCHelperSessionPrivateRef       sessionPrivate  = (SCHelperSessionPrivateRef)session;
 
+       /*
+        * On OSX, the authorizationData can either be a CFData-wrapped/externalized
+        * "authorization" or a CFString indicating that we should check entitlements.
+        *
+        * On iOS, the authorizationData is a CFString indicating that we should
+        * check entitlements.
+        */
        pthread_mutex_lock(&sessionPrivate->lock);
 
        if (sessionPrivate->authorization != NULL) {
-#if !TARGET_OS_IPHONE
+#if    !TARGET_OS_IPHONE
                if (!__SCHelperSessionUseEntitlement(session)) {
                        AuthorizationFree(sessionPrivate->authorization, kAuthorizationFlagDefaults);
 //                     AuthorizationFree(sessionPrivate->authorization, kAuthorizationFlagDestroyRights);
-                       sessionPrivate->authorization = NULL;
                } else {
-#endif //!TARGET_OS_IPHONE
                        CFRelease(sessionPrivate->authorization);
-                       sessionPrivate->authorization = NULL;
-#if !TARGET_OS_IPHONE
                }
-#endif //!TARGET_OS_IPHONE
+#else  //!TARGET_OS_IPHONE
+               CFRelease(sessionPrivate->authorization);
+#endif //!TARGET_OS_IPHONE
+               sessionPrivate->authorization = NULL;
                sessionPrivate->use_entitlement = FALSE;
        }
 
-#if !TARGET_OS_IPHONE
+#if    !TARGET_OS_IPHONE
        if (isA_CFData(authorizationData)) {
                AuthorizationExternalForm       extForm;
 
@@ -181,13 +193,16 @@ __SCHelperSessionSetAuthorization(SCHelperSessionRef session, CFTypeRef authoriz
                                ok = FALSE;
                        }
                }
-       } else
-#endif //!TARGET_OS_IPHONE
-
+       } else if (isA_CFString(authorizationData)) {
+               sessionPrivate->authorization = (void *)CFRetain(authorizationData);
+               sessionPrivate->use_entitlement = TRUE;
+       }
+#else  //!TARGET_OS_IPHONE
        if (isA_CFString(authorizationData)) {
                sessionPrivate->authorization = (void *)CFRetain(authorizationData);
                sessionPrivate->use_entitlement = TRUE;
        }
+#endif //!TARGET_OS_IPHONE
 
        pthread_mutex_unlock(&sessionPrivate->lock);
 
@@ -287,29 +302,46 @@ __SCHelperSessionSetPreferences(SCHelperSessionRef session, SCPreferencesRef pre
 }
 
 
-static CFArrayRef
-__SCHelperSessionGetVPNFilter(SCHelperSessionRef session)
+static void
+__SCHelperSessionSetNetworkSetFilter(SCHelperSessionRef session, Boolean setChange)
 {
        SCHelperSessionPrivateRef       sessionPrivate  = (SCHelperSessionPrivateRef)session;
 
-       return sessionPrivate->vpnFilter;
+       pthread_mutex_lock(&sessionPrivate->lock);
+
+       sessionPrivate->isSetChange = setChange ? YES : NO;
+
+       pthread_mutex_unlock(&sessionPrivate->lock);
+
+       return;
 }
 
 
 static Boolean
-__SCHelperSessionSetVPNFilter(SCHelperSessionRef session, CFArrayRef vpnFilter)
+__SCHelperSessionUseNetworkSetFilter(SCHelperSessionRef session)
+{
+       SCHelperSessionPrivateRef       sessionPrivate  = (SCHelperSessionPrivateRef)session;
+
+       return (sessionPrivate->isSetChange == YES) ? TRUE : FALSE;
+}
+
+
+static Boolean
+__SCHelperSessionSetVPNFilter(SCHelperSessionRef session, Boolean vpnChange, CFArrayRef vpnTypes)
 {
        SCHelperSessionPrivateRef       sessionPrivate  = (SCHelperSessionPrivateRef)session;
 
        pthread_mutex_lock(&sessionPrivate->lock);
 
-       if (vpnFilter != NULL) {
-               CFRetain(vpnFilter);
+       sessionPrivate->isVPNChange = vpnChange ? YES : NO;
+
+       if (vpnTypes != NULL) {
+               CFRetain(vpnTypes);
        }
-       if (sessionPrivate->vpnFilter != NULL) {
-               CFRelease(sessionPrivate->vpnFilter);
+       if (sessionPrivate->vpnTypes != NULL) {
+               CFRelease(sessionPrivate->vpnTypes);
        }
-       sessionPrivate->vpnFilter = vpnFilter;
+       sessionPrivate->vpnTypes = vpnTypes;
 
        pthread_mutex_unlock(&sessionPrivate->lock);
 
@@ -317,6 +349,16 @@ __SCHelperSessionSetVPNFilter(SCHelperSessionRef session, CFArrayRef vpnFilter)
 }
 
 
+static CFArrayRef
+__SCHelperSessionUseVPNFilter(SCHelperSessionRef session, CFArrayRef *vpnTypes)
+{
+       SCHelperSessionPrivateRef       sessionPrivate  = (SCHelperSessionPrivateRef)session;
+
+       *vpnTypes = sessionPrivate->vpnTypes;
+       return (sessionPrivate->vpnTypes != NULL) ? TRUE : FALSE;
+}
+
+
 static void
 __SCHelperSessionLog(const void *value, void *context)
 {
@@ -387,7 +429,7 @@ __SCHelperSessionCopyDescription(CFTypeRef cf)
        CFStringAppendFormat(result, NULL, CFSTR("authorization = %p"), sessionPrivate->authorization);
        if (sessionPrivate->mp != NULL) {
                CFStringAppendFormat(result, NULL,
-                                    CFSTR(", mp = %p (port = %p)"),
+                                    CFSTR(", mp = %p (port = 0x%x)"),
                                     sessionPrivate->mp,
                                     CFMachPortGetPort(sessionPrivate->mp));
        }
@@ -413,8 +455,9 @@ __SCHelperSessionDeallocate(CFTypeRef cf)
 
        // release resources
        __SCHelperSessionSetAuthorization(session, NULL);
-       __SCHelperSessionSetPreferences  (session, NULL);
-       __SCHelperSessionSetVPNFilter    (session, NULL);
+       __SCHelperSessionSetPreferences(session, NULL);
+       __SCHelperSessionSetNetworkSetFilter(session, FALSE);
+       __SCHelperSessionSetVPNFilter(session, FALSE, NULL);
        pthread_mutex_destroy(&sessionPrivate->lock);
        if (sessionPrivate->backtraces != NULL) {
                CFRelease(sessionPrivate->backtraces);
@@ -469,8 +512,11 @@ __SCHelperSessionCreate(CFAllocatorRef allocator)
        sessionPrivate->use_entitlement         = FALSE;
        sessionPrivate->port                    = MACH_PORT_NULL;
        sessionPrivate->mp                      = NULL;
+       sessionPrivate->callerReadAccess        = UNKNOWN;
        sessionPrivate->callerWriteAccess       = UNKNOWN;
-       sessionPrivate->vpnFilter               = NULL;
+       sessionPrivate->isSetChange             = UNKNOWN;
+       sessionPrivate->isVPNChange             = UNKNOWN;
+       sessionPrivate->vpnTypes                = NULL;
        sessionPrivate->prefs                   = NULL;
        sessionPrivate->backtraces              = NULL;
 
@@ -635,7 +681,7 @@ static Boolean
 do_Auth(SCHelperSessionRef session, void *info, CFDataRef data, uint32_t *status, CFDataRef *reply)
 {
        CFDictionaryRef authorizationDict;
-#if !TARGET_OS_IPHONE
+#if    !TARGET_OS_IPHONE
        CFDataRef       authorizationData       = NULL;
 #endif
        Boolean         ok                      = FALSE;
@@ -644,19 +690,23 @@ do_Auth(SCHelperSessionRef session, void *info, CFDataRef data, uint32_t *status
                return FALSE;
        }
 
-       if (isA_CFDictionary(authorizationDict) == FALSE) {
+       if (authorizationDict == NULL) {
+               return FALSE;
+       }
+
+       if (!isA_CFDictionary(authorizationDict)) {
                CFRelease(authorizationDict);
                return FALSE;
        }
 
-#if !TARGET_OS_IPHONE
+#if    !TARGET_OS_IPHONE
        authorizationData = CFDictionaryGetValue(authorizationDict, kSCHelperAuthAuthorization);
        if (authorizationData != NULL && isA_CFData(authorizationData)) {
                ok = __SCHelperSessionSetAuthorization(session, authorizationData);
        } else
 #endif
        {
-               CFStringRef authorizationInfo;
+               CFStringRef     authorizationInfo;
 
                authorizationInfo = CFDictionaryGetValue(authorizationDict, kSCHelperAuthCallerInfo);
                if (authorizationInfo != NULL && isA_CFString(authorizationInfo)) {
@@ -1123,38 +1173,42 @@ do_prefs_Commit(SCHelperSessionRef session, void *info, CFDataRef data, uint32_t
        SCPreferencesRef        prefs           = __SCHelperSessionGetPreferences(session);
        CFPropertyListRef       prefsData       = NULL;
        SCPreferencesPrivateRef prefsPrivate    = (SCPreferencesPrivateRef)prefs;
-       CFArrayRef              vpnFilter;
+       Boolean                 useSetFilter;
+       Boolean                 useVPNFilter;
+       CFArrayRef              vpnTypes        = NULL;
 
        if (prefs == NULL) {
                return FALSE;
        }
 
-       if (data != NULL) {
-               ok = _SCUnserialize(&prefsData, data, NULL, 0);
-               if (!ok) {
-                       return FALSE;
-               }
+       if (data == NULL) {
+               // if commit with no changes
+               goto commit;
+       }
 
-               if (!isA_CFDictionary(prefsData)) {
-                       *status = kSCStatusFailed;
-                       ok = FALSE;
-                       goto done;
-               }
+       ok = _SCUnserialize(&prefsData, data, NULL, 0);
+       if (!ok) {
+               return FALSE;
        }
 
-       vpnFilter = __SCHelperSessionGetVPNFilter(session);
-       if (vpnFilter != NULL) {
+       if (!isA_CFDictionary(prefsData)) {
+               *status = kSCStatusFailed;
                ok = FALSE;
+               goto done;
+       }
 
-               if ((prefsPrivate->prefs != NULL) && (prefsData != NULL)) {
+       useSetFilter = __SCHelperSessionUseNetworkSetFilter(session);
+       useVPNFilter = __SCHelperSessionUseVPNFilter(session, &vpnTypes);
+       if (useSetFilter || useVPNFilter) {
+               ok = FALSE;
+
+               if (prefsPrivate->prefs != NULL) {
                        CFIndex                 c;
                        CFMutableDictionaryRef  prefsNew        = NULL;
                        CFMutableDictionaryRef  prefsOld        = NULL;
                        CFMutableDictionaryRef  prefsSave       = prefsPrivate->prefs;
-                       CFRange                 range           = CFRangeMake(0, CFArrayGetCount(vpnFilter));
 
                        for (c = 0; c < 2; c++) {
-                               CFArrayRef      services;
 
                                switch (c) {
                                        case 0 :
@@ -1165,41 +1219,49 @@ do_prefs_Commit(SCHelperSessionRef session, void *info, CFDataRef data, uint32_t
                                                break;
                                }
 
-                               // filter out VPN services of the specified type
-                               services = SCNetworkServiceCopyAll(prefs);
-                               if (services != NULL) {
-                                       CFIndex i;
-                                       CFIndex n       = CFArrayGetCount(services);
-
-                                       for (i = 0; i < n; i++) {
-                                               SCNetworkServiceRef     service;
-
-                                               service = CFArrayGetValueAtIndex(services, i);
-                                               if (_SCNetworkServiceIsVPN(service)) {
-                                                       SCNetworkInterfaceRef   child;
-                                                       CFStringRef             childType       = NULL;
-                                                       SCNetworkInterfaceRef   interface;
-                                                       CFStringRef             interfaceType;
-
-                                                       interface     = SCNetworkServiceGetInterface(service);
-                                                       interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
-                                                       child         = SCNetworkInterfaceGetInterface(interface);
-                                                       if (child != NULL) {
-                                                               childType = SCNetworkInterfaceGetInterfaceType(child);
-                                                       }
-                                                       if (CFEqual(interfaceType, kSCNetworkInterfaceTypeVPN) &&
-                                                           (childType != NULL) &&
-                                                           CFArrayContainsValue(vpnFilter, range, childType)) {
-                                                               // filter out VPN service
-                                                               (void) SCNetworkServiceRemove(service);
-                                                       } else {
-                                                               // mark all other VPN services "enabled"
-                                                               (void) SCNetworkServiceSetEnabled(service, TRUE);
+                               if (useSetFilter) {
+                                       // filter out current network set selection
+                                       (void) SCPreferencesRemoveValue(prefs, kSCPrefCurrentSet);
+                               } else if (useVPNFilter) {
+                                       CFRange         range           = CFRangeMake(0, CFArrayGetCount(vpnTypes));
+                                       CFArrayRef      services;
+
+                                       // filter out VPN services of the specified type
+                                       services = SCNetworkServiceCopyAll(prefs);
+                                       if (services != NULL) {
+                                               CFIndex i;
+                                               CFIndex n       = CFArrayGetCount(services);
+
+                                               for (i = 0; i < n; i++) {
+                                                       SCNetworkServiceRef     service;
+
+                                                       service = CFArrayGetValueAtIndex(services, i);
+                                                       if (_SCNetworkServiceIsVPN(service)) {
+                                                               SCNetworkInterfaceRef   child;
+                                                               CFStringRef             childType       = NULL;
+                                                               SCNetworkInterfaceRef   interface;
+                                                               CFStringRef             interfaceType;
+
+                                                               interface     = SCNetworkServiceGetInterface(service);
+                                                               interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
+                                                               child         = SCNetworkInterfaceGetInterface(interface);
+                                                               if (child != NULL) {
+                                                                       childType = SCNetworkInterfaceGetInterfaceType(child);
+                                                               }
+                                                               if (CFEqual(interfaceType, kSCNetworkInterfaceTypeVPN) &&
+                                                                   (childType != NULL) &&
+                                                                   CFArrayContainsValue(vpnTypes, range, childType)) {
+                                                                       // filter out VPN service
+                                                                       (void) SCNetworkServiceRemove(service);
+                                                               } else {
+                                                                       // mark all other VPN services "enabled"
+                                                                       (void) SCNetworkServiceSetEnabled(service, TRUE);
+                                                               }
                                                        }
                                                }
-                                       }
 
-                                       CFRelease(services);
+                                               CFRelease(services);
+                                       }
                                }
 
                                switch (c) {
@@ -1227,14 +1289,14 @@ do_prefs_Commit(SCHelperSessionRef session, void *info, CFDataRef data, uint32_t
                }
        }
 
-       if (prefsData != NULL) {
-               if (prefsPrivate->prefs != NULL) {
-                       CFRelease(prefsPrivate->prefs);
-               }
-               prefsPrivate->prefs    = CFDictionaryCreateMutableCopy(NULL, 0, prefsData);
-               prefsPrivate->accessed = TRUE;
-               prefsPrivate->changed  = TRUE;
+       if (prefsPrivate->prefs != NULL) {
+               CFRelease(prefsPrivate->prefs);
        }
+       prefsPrivate->prefs    = CFDictionaryCreateMutableCopy(NULL, 0, prefsData);
+       prefsPrivate->accessed = TRUE;
+       prefsPrivate->changed  = TRUE;
+
+    commit :
 
        ok = SCPreferencesCommitChanges(prefs);
        if (ok) {
@@ -1364,6 +1426,24 @@ sessionName(SCHelperSessionRef session)
 }
 
 
+static CFStringRef
+sessionPrefsID(SCHelperSessionRef session)
+{
+       CFStringRef                     prefsID;
+       SCPreferencesPrivateRef         prefsPrivate;
+       SCHelperSessionPrivateRef       sessionPrivate  = (SCHelperSessionPrivateRef)session;
+
+       prefsPrivate = (SCPreferencesPrivateRef)sessionPrivate->prefs;
+       if ((prefsPrivate != NULL) && (prefsPrivate->prefsID != NULL)) {
+               prefsID  = prefsPrivate->prefsID;
+       } else {
+               prefsID = PREFS_DEFAULT_CONFIG;
+       }
+
+       return prefsID;
+}
+
+
 static CFTypeRef
 copyEntitlement(SCHelperSessionRef session, CFStringRef entitlement)
 {
@@ -1405,34 +1485,173 @@ copyEntitlement(SCHelperSessionRef session, CFStringRef entitlement)
 }
 
 
+#if    !TARGET_OS_IPHONE
+static Boolean
+isSetChange(SCHelperSessionRef session)
+{
+       SCHelperSessionPrivateRef       sessionPrivate  = (SCHelperSessionPrivateRef)session;
+
+       if (sessionPrivate->isSetChange == UNKNOWN) {
+               CFBooleanRef                    bVal            = NULL;
+               CFStringRef                     prefsID;
+               SCPreferencesPrivateRef         prefsPrivate    = (SCPreferencesPrivateRef)sessionPrivate->prefs;
+               Boolean                         setFilter       = FALSE;
+
+               prefsID = sessionPrefsID(session);
+               if (CFEqual(prefsID, PREFS_DEFAULT_CONFIG) &&
+                   isA_CFDictionary(prefsPrivate->options) &&
+                   CFDictionaryGetValueIfPresent(prefsPrivate->options,
+                                                 kSCPreferencesOptionChangeNetworkSet,
+                                                 (const void **)&bVal) &&
+                   isA_CFBoolean(bVal) &&
+                   CFBooleanGetValue(bVal)) {
+                       setFilter = TRUE;
+               }
+
+               // establish network set (location) filter
+               __SCHelperSessionSetNetworkSetFilter(session, setFilter);
+       }
+
+       return (sessionPrivate->isSetChange == YES) ? TRUE : FALSE;
+}
+#endif // !TARGET_OS_IPHONE
+
+
 static Boolean
-hasAuthorization(SCHelperSessionRef session)
+isVPNChange(SCHelperSessionRef session)
 {
-       AuthorizationRef                authorization   = __SCHelperSessionGetAuthorization(session);
        SCHelperSessionPrivateRef       sessionPrivate  = (SCHelperSessionPrivateRef)session;
 
+       if (sessionPrivate->isVPNChange == UNKNOWN) {
+               CFArrayRef      entitlement;
+               Boolean         vpnChange       = FALSE;
+               CFArrayRef      vpnTypes        = NULL;
+
+               entitlement = copyEntitlement(session, kSCVPNFilterEntitlementName);
+               if (entitlement != NULL) {
+                       if (isA_CFArray(entitlement)) {
+                               CFStringRef     prefsID;
+
+                               prefsID = sessionPrefsID(session);
+                               if (CFEqual(prefsID, PREFS_DEFAULT_CONFIG)) {
+                                       // save the VPN type identifiers
+                                       vpnTypes = CFRetain(entitlement);
+
+                                       // grant an exception
+                                       vpnChange = TRUE;
+                               } else if (CFStringHasPrefix(prefsID, CFSTR("VPN-")) &&
+                                          CFStringHasSuffix(prefsID, CFSTR(".plist"))) {
+                                       CFRange         range;
+                                       CFStringRef     vpnID;
+
+                                       range.location = sizeof("VPN-") - 1;
+                                       range.length   = CFStringGetLength(prefsID)
+                                                        - (sizeof("VPN-") - 1)         // trim VPN-
+                                                        - (sizeof(".plist") - 1);      // trim .plist
+                                       vpnID = CFStringCreateWithSubstring(NULL, prefsID, range);
+                                       if (CFArrayContainsValue(entitlement,
+                                                                CFRangeMake(0, CFArrayGetCount(entitlement)),
+                                                                vpnID)) {
+                                               // grant an exception
+                                               vpnChange = TRUE;
+                                       }
+                                       CFRelease(vpnID);
+                               }
+                       }
+
+                       CFRelease(entitlement);
+               }
+
+               __SCHelperSessionSetVPNFilter(session, vpnChange, vpnTypes);
+               if (vpnTypes != NULL) {
+                       CFRelease(vpnTypes);
+               }
+       }
+
+       return (sessionPrivate->isVPNChange == YES) ? TRUE : FALSE;
+}
+
+
+static Boolean
+checkEntitlement(SCHelperSessionRef session, CFStringRef prefsID, CFStringRef entitlement_name)
+{
+       CFArrayRef                      entitlement;
+       Boolean                         hasEntitlement  = FALSE;
+
+       entitlement = copyEntitlement(session, entitlement_name);
+       if (entitlement != NULL) {
+               if (isA_CFArray(entitlement)) {
+                       if (CFArrayContainsValue(entitlement,
+                                                CFRangeMake(0, CFArrayGetCount(entitlement)),
+                                                prefsID)) {
+                               // if client DOES have entitlement
+                               hasEntitlement = TRUE;
+                       }
+               } else {
+                       SCLog(TRUE, LOG_ERR,
+                             CFSTR("hasAuthorization() entitlement=%@: not valid"),
+                             entitlement_name,
+                             sessionName(session));
+               }
+
+               CFRelease(entitlement);
+       }
+
+#if    TARGET_OS_IPHONE
+       // make an exception for VPN configuration management
+       if (!hasEntitlement) {
+               if (isVPNChange(session)) {
+                       // grant a "filtered" exception
+                       hasEntitlement = TRUE;
+               }
+       }
+#endif // TARGET_OS_IPHONE
+
+       return hasEntitlement;
+}
+
+
+static Boolean
+hasAuthorization(SCHelperSessionRef session, Boolean needWrite)
+{
+       AuthorizationRef                authorization           = __SCHelperSessionGetAuthorization(session);
+       CFStringRef                     prefsID;
+       SCHelperSessionPrivateRef       sessionPrivate          = (SCHelperSessionPrivateRef)session;
+
        if (authorization == NULL) {
                return FALSE;
        }
 
-#if !TARGET_OS_IPHONE
+#if    !TARGET_OS_IPHONE
        if (!__SCHelperSessionUseEntitlement(session)) {
                AuthorizationFlags      flags;
                AuthorizationItem       items[1];
                AuthorizationRights     rights;
                OSStatus                status;
 
-               items[0].name        = kSCPreferencesWriteAuthorizationRight;
-               items[0].value       = NULL;
-               items[0].valueLength = 0;
-               items[0].flags       = 0;
+               if (isSetChange(session)) {
+                       items[0].name        = kSCPreferencesAuthorizationRight_network_set;
+                       items[0].value       = NULL;
+                       items[0].valueLength = 0;
+                       items[0].flags       = 0;
+               } else if (isVPNChange(session)) {
+                       items[0].name        = kSCPreferencesAuthorizationRight_write;
+                       items[0].value       = NULL;
+                       items[0].valueLength = 0;
+                       items[0].flags       = 0;
+               } else {
+                       items[0].name        = kSCPreferencesAuthorizationRight_write;
+                       items[0].value       = NULL;
+                       items[0].valueLength = 0;
+                       items[0].flags       = 0;
+               }
 
                rights.count = sizeof(items) / sizeof(items[0]);
                rights.items = items;
 
                flags = kAuthorizationFlagDefaults;
-               flags |= kAuthorizationFlagExtendRights;
                flags |= kAuthorizationFlagInteractionAllowed;
+               flags |= kAuthorizationFlagExtendRights;
 //             flags |= kAuthorizationFlagPartialRights;
 //             flags |= kAuthorizationFlagPreAuthorize;
 
@@ -1447,81 +1666,48 @@ hasAuthorization(SCHelperSessionRef session)
 
                return TRUE;
        }
-#endif // !TARGET_OS_IPHONE
-
-       if (sessionPrivate->callerWriteAccess == UNKNOWN) {
-               CFArrayRef              entitlement;
-               CFStringRef             prefsID;
-               SCPreferencesPrivateRef prefsPrivate;
-
-               // assume that the client DOES NOT have the entitlement
-               sessionPrivate->callerWriteAccess = NO;
-
-               prefsPrivate = (SCPreferencesPrivateRef)sessionPrivate->prefs;
-               prefsID      = (prefsPrivate->prefsID != NULL) ? prefsPrivate->prefsID : PREFS_DEFAULT_CONFIG;
-
-               entitlement = copyEntitlement(session, kSCWriteEntitlementName);
-               if (entitlement != NULL) {
-                       if (isA_CFArray(entitlement)) {
-                               if (CFArrayContainsValue(entitlement,
-                                                        CFRangeMake(0, CFArrayGetCount(entitlement)),
-                                                        prefsID)) {
-                                       // if client DOES have entitlement
-                                       sessionPrivate->callerWriteAccess = YES;
-                               }
-                       } else {
-                               SCLog(TRUE, LOG_ERR,
-                                     CFSTR("hasAuthorization: entitlement not valid: %@"),
-                                     sessionName(session));
-                       }
-
-                       CFRelease(entitlement);
-               }
+#endif // !TARGET_OS_IPHONE
 
-               // make an exception for VPN configuration management
-               if (sessionPrivate->callerWriteAccess != YES) {
-                       entitlement = copyEntitlement(session, kSCVPNFilterEntitlementName);
-                       if (entitlement != NULL) {
-                               if (isA_CFArray(entitlement)) {
-                                       if (CFEqual(prefsID, PREFS_DEFAULT_CONFIG)) {
-                                               // save the VPN bundle identifiers
-                                               __SCHelperSessionSetVPNFilter(session, entitlement);
-
-                                               // and grant a "filtered" exception
-                                               sessionPrivate->callerWriteAccess = YES;
-                                       } else if (CFStringHasPrefix(prefsID, CFSTR("VPN-")) &&
-                                                  CFStringHasSuffix(prefsID, CFSTR(".plist"))) {
-                                               CFRange         range;
-                                               CFStringRef     vpnID;
-
-                                               range.location = sizeof("VPN-") - 1;
-                                               range.length   = CFStringGetLength(prefsID)
-                                                                - (sizeof("VPN-") - 1)         // trim VPN-
-                                                                - (sizeof(".plist") - 1);      // trim .plist
-                                               vpnID = CFStringCreateWithSubstring(NULL, prefsID, range);
-                                               if (CFArrayContainsValue(entitlement,
-                                                                        CFRangeMake(0, CFArrayGetCount(entitlement)),
-                                                                        vpnID)) {
-                                                       // grant an exception
-                                                       sessionPrivate->callerWriteAccess = YES;
-                                               }
-                                               CFRelease(vpnID);
-                                       }
-                               }
+       prefsID = sessionPrefsID(session);
 
-                               CFRelease(entitlement);
-                       }
+       if (sessionPrivate->callerWriteAccess == UNKNOWN) {
+               if (checkEntitlement(session, prefsID, kSCWriteEntitlementName)) {
+                       sessionPrivate->callerWriteAccess = YES;
+                       sessionPrivate->callerReadAccess  = YES;        // implied
+               } else {
+                       sessionPrivate->callerWriteAccess = NO;
                }
+       }
 
-               if (sessionPrivate->callerWriteAccess != YES) {
+       if (needWrite) {
+               if (sessionPrivate->callerWriteAccess == YES) {
+                       return TRUE;
+               } else {
                        SCLog(TRUE, LOG_ERR,
                              CFSTR("SCPreferences write access to \"%@\" denied, no entitlement for \"%@\""),
                              prefsID,
                              sessionName(session));
+                       return FALSE;
+               }
+       }
+
+       if (sessionPrivate->callerReadAccess == UNKNOWN) {
+               if (checkEntitlement(session, prefsID, kSCReadEntitlementName)) {
+                       sessionPrivate->callerReadAccess  = YES;
+               } else {
+                       sessionPrivate->callerWriteAccess = NO;
                }
        }
 
-       return (sessionPrivate->callerWriteAccess == YES) ? TRUE : FALSE;
+       if (sessionPrivate->callerReadAccess == YES) {
+               return TRUE;
+       }
+
+       SCLog(TRUE, LOG_ERR,
+             CFSTR("SCPreferences access to \"%@\" denied, no entitlement for \"%@\""),
+             prefsID,
+             sessionName(session));
+       return FALSE;
 }
 
 
@@ -1536,31 +1722,32 @@ static const struct helper {
        int             command;
        const char      *commandName;
        Boolean         needsAuthorization;
+       Boolean         needsWrite;
        helperFunction  func;
        void            *info;
 } helpers[] = {
-       { SCHELPER_MSG_AUTH,                    "AUTH",                 FALSE,  do_Auth                 , NULL          },
+       { SCHELPER_MSG_AUTH,                    "AUTH",                 FALSE,  FALSE,  do_Auth                 , NULL          },
 
-       { SCHELPER_MSG_PREFS_OPEN,              "PREFS open",           FALSE,  do_prefs_Open           , NULL          },
-       { SCHELPER_MSG_PREFS_ACCESS,            "PREFS access",         TRUE,   do_prefs_Access         , NULL          },
-       { SCHELPER_MSG_PREFS_LOCK,              "PREFS lock",           TRUE,   do_prefs_Lock           , (void *)FALSE },
-       { SCHELPER_MSG_PREFS_LOCKWAIT,          "PREFS lock/wait",      TRUE,   do_prefs_Lock           , (void *)TRUE  },
-       { SCHELPER_MSG_PREFS_COMMIT,            "PREFS commit",         TRUE,   do_prefs_Commit         , NULL          },
-       { SCHELPER_MSG_PREFS_APPLY,             "PREFS apply",          TRUE,   do_prefs_Apply          , NULL          },
-       { SCHELPER_MSG_PREFS_UNLOCK,            "PREFS unlock",         FALSE,  do_prefs_Unlock         , NULL          },
-       { SCHELPER_MSG_PREFS_CLOSE,             "PREFS close",          FALSE,  do_prefs_Close          , NULL          },
-       { SCHELPER_MSG_PREFS_SYNCHRONIZE,       "PREFS synchronize",    FALSE,  do_prefs_Synchronize    , NULL          },
+       { SCHELPER_MSG_PREFS_OPEN,              "PREFS open",           FALSE,  FALSE,  do_prefs_Open           , NULL          },
+       { SCHELPER_MSG_PREFS_ACCESS,            "PREFS access",         TRUE,   FALSE,  do_prefs_Access         , NULL          },
+       { SCHELPER_MSG_PREFS_LOCK,              "PREFS lock",           TRUE,   TRUE,   do_prefs_Lock           , (void *)FALSE },
+       { SCHELPER_MSG_PREFS_LOCKWAIT,          "PREFS lock/wait",      TRUE,   TRUE,   do_prefs_Lock           , (void *)TRUE  },
+       { SCHELPER_MSG_PREFS_COMMIT,            "PREFS commit",         TRUE,   TRUE,   do_prefs_Commit         , NULL          },
+       { SCHELPER_MSG_PREFS_APPLY,             "PREFS apply",          TRUE,   TRUE,   do_prefs_Apply          , NULL          },
+       { SCHELPER_MSG_PREFS_UNLOCK,            "PREFS unlock",         FALSE,  TRUE,   do_prefs_Unlock         , NULL          },
+       { SCHELPER_MSG_PREFS_CLOSE,             "PREFS close",          FALSE,  FALSE,  do_prefs_Close          , NULL          },
+       { SCHELPER_MSG_PREFS_SYNCHRONIZE,       "PREFS synchronize",    FALSE,  FALSE,  do_prefs_Synchronize    , NULL          },
 
-       { SCHELPER_MSG_INTERFACE_REFRESH,       "INTERFACE refresh",    TRUE,   do_interface_refresh    , NULL          },
+       { SCHELPER_MSG_INTERFACE_REFRESH,       "INTERFACE refresh",    TRUE,   TRUE,   do_interface_refresh    , NULL          },
 
 #if    !TARGET_OS_IPHONE
-       { SCHELPER_MSG_KEYCHAIN_COPY,           "KEYCHAIN copy",        TRUE,   do_keychain_copy        , NULL          },
-       { SCHELPER_MSG_KEYCHAIN_EXISTS,         "KEYCHAIN exists",      TRUE,   do_keychain_exists      , NULL          },
-       { SCHELPER_MSG_KEYCHAIN_REMOVE,         "KEYCHAIN remove",      TRUE,   do_keychain_remove      , NULL          },
-       { SCHELPER_MSG_KEYCHAIN_SET,            "KEYCHAIN set",         TRUE,   do_keychain_set         , NULL          },
+       { SCHELPER_MSG_KEYCHAIN_COPY,           "KEYCHAIN copy",        TRUE,   FALSE,  do_keychain_copy        , NULL          },
+       { SCHELPER_MSG_KEYCHAIN_EXISTS,         "KEYCHAIN exists",      TRUE,   FALSE,  do_keychain_exists      , NULL          },
+       { SCHELPER_MSG_KEYCHAIN_REMOVE,         "KEYCHAIN remove",      TRUE,   TRUE,   do_keychain_remove      , NULL          },
+       { SCHELPER_MSG_KEYCHAIN_SET,            "KEYCHAIN set",         TRUE,   TRUE,   do_keychain_set         , NULL          },
 #endif // !TARGET_OS_IPHONE
 
-       { SCHELPER_MSG_EXIT,                    "EXIT",                 FALSE,  do_Exit                 , NULL          }
+       { SCHELPER_MSG_EXIT,                    "EXIT",                 FALSE,  FALSE,  do_Exit                 , NULL          }
 };
 #define nHELPERS (sizeof(helpers)/sizeof(struct helper))
 
@@ -1587,6 +1774,9 @@ newHelper(void *arg)
        SCHelperSessionRef              session         = (SCHelperSessionRef)arg;
        SCHelperSessionPrivateRef       sessionPrivate  = (SCHelperSessionPrivateRef)session;
 
+       assert(session != NULL);
+       assert(sessionPrivate->mp != NULL);
+
        __SCHelperSessionSetThreadName(session);
 
        rls = CFMachPortCreateRunLoopSource(NULL, sessionPrivate->mp, 0);
@@ -1726,6 +1916,10 @@ helperCallback(CFMachPortRef port, void *msg, CFIndex size, void *info)
        static CFIndex          bufSize         = 0;
        mach_msg_return_t       mr;
        int                     options;
+       int                     ret             = 0;
+       uint64_t                token;
+
+       ret = proc_importance_assertion_begin_with_msg(&bufRequest->Head, NULL, &token);
 
        if (bufSize == 0) {
                // get max size for MiG reply buffers
@@ -1800,7 +1994,11 @@ helperCallback(CFMachPortRef port, void *msg, CFIndex size, void *info)
                mach_msg_destroy(&bufReply->Head);
        }
 
-       done :
+    done :
+
+       if (ret == 0) {
+               proc_importance_assertion_complete(token);
+       }
 
        if (bufReply != (mig_reply_error_t *)bufReply_q)
                CFAllocatorDeallocate(NULL, bufReply);
@@ -1845,6 +2043,7 @@ _helperinit(mach_port_t                   server,
        }
 
        session = __SCHelperSessionCreate(NULL);
+       assert(session != NULL);
        sessionPrivate = (SCHelperSessionPrivateRef)session;
 
        // create per-session port
@@ -1853,6 +2052,12 @@ _helperinit(mach_port_t                  server,
                                  &sessionPrivate->port);
        *newSession = sessionPrivate->port;
 
+       (void) mach_port_set_attributes(mach_task_self(),
+                                       *newSession,
+                                       MACH_PORT_IMPORTANCE_RECEIVER,
+                                       NULL,
+                                       0);
+
        //
        // Note: we create the CFMachPort *before* we insert a send
        //       right present to ensure that CF does not establish
@@ -1978,7 +2183,8 @@ _helperexec(mach_port_t                   server,
              helpers[i].commandName,
              (data != NULL) ? " w/data" : "");
 
-       if (helpers[i].needsAuthorization && !hasAuthorization(session)) {
+       if (helpers[i].needsAuthorization &&
+           !hasAuthorization(session, helpers[i].needsWrite)) {
                SCLog(debug, LOG_DEBUG,
                      CFSTR("%p : command \"%s\" : not authorized"),
                      session,
index abf809552cd0d578fa4c357805df8a93fcb24db2..bafb82f9210b45ac57b9c6bce2f91d0d70331f94 100644 (file)
@@ -11,5 +11,7 @@
                <key>com.apple.SystemConfiguration.helper</key>
                <true/>
        </dict>
+       <key>POSIXSpawnType</key>
+       <string>Adaptive</string>
 </dict>
 </plist>
index ee55286d4bf9be294fed1beac06965d635fb9ba3..b6612a4f89b5ab0d3fb512f4988d2208febcb4a0 100644 (file)
@@ -5,11 +5,13 @@
        <key>Label</key>
        <string>com.apple.SCHelper</string>
        <key>Program</key>
-       <string>/System/Library/Frameworks/SystemConfiguration.framework/Resources/SCHelper</string>
+       <string>/System/Library/Frameworks/SystemConfiguration.framework/Versions/A/Helpers/SCHelper</string>
        <key>MachServices</key>
        <dict>
                <key>com.apple.SystemConfiguration.helper</key>
                <true/>
        </dict>
+       <key>POSIXSpawnType</key>
+       <string>Adaptive</string>
 </dict>
 </plist>
index 09c0ea64dab65b3451d11ee0e71762ae48eeff28..13196ea568d20d6d87184dfca19ccd412a2fe695 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012 Apple Inc. All rights reserved.
+ * Copyright (c) 2011-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 
 #include <xpc/xpc.h>
 #include <xpc/private.h>
-
-#include "rb.h"
+#include <sys/rbtree.h>
 
 
 #pragma mark -
 #pragma mark Globals
 
 
-static const struct addrinfo   hints0  = {
-#ifdef  AI_PARALLEL
-       .ai_flags       = AI_PARALLEL | AI_ADDRCONFIG
-#else  // AI_PARALLEL
-       .ai_flags       = AI_ADDRCONFIG
-#endif  // AI_PARALLEL
-};
-
-
 static Boolean                 serverAvailable = TRUE;
 
 
@@ -70,50 +60,48 @@ log_xpc_object(const char *msg, xpc_object_t obj)
 
 
 typedef struct {
-       struct rb_node                  rbn;
+       rb_node_t                       rbn;
        SCNetworkReachabilityRef        target;
 } reach_request_t;
 
 
-#define RBNODE_TO_REACH_REQUEST(node) \
-       ((reach_request_t *)((uintptr_t)node - offsetof(reach_request_t, rbn)))
-
-
 static int
-_rbt_compare_transaction_nodes(const struct rb_node *n1, const struct rb_node *n2)
+_rbt_compare_transaction_nodes(void *context, const void *n1, const void *n2)
 {
-       uint64_t        a = (uintptr_t)(RBNODE_TO_REACH_REQUEST(n1)->target);
-       uint64_t        b = (uintptr_t)(RBNODE_TO_REACH_REQUEST(n2)->target);
+       uint64_t        a = (uintptr_t)(((reach_request_t *)n1)->target);
+       uint64_t        b = (uintptr_t)(((reach_request_t *)n2)->target);
 
        return (a - b);
 }
 
 
 static int
-_rbt_compare_transaction_key(const struct rb_node *n1, const void *key)
+_rbt_compare_transaction_key(void *context, const void *n1, const void *key)
 {
-       uint64_t        a = (uintptr_t)(RBNODE_TO_REACH_REQUEST(n1)->target);
+       uint64_t        a = (uintptr_t)(((reach_request_t *)n1)->target);
        uint64_t        b = *(uint64_t *)key;
 
        return (a - b);
 }
 
 
-static struct rb_tree *
+static rb_tree_t *
 _reach_requests_rbt()
 {
        static dispatch_once_t          once;
-       static const struct rb_tree_ops ops = {
+       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_request_t, rbn),
+               .rbto_context           = NULL
        };
-       static struct rb_tree           rbtree;
+       static rb_tree_t                rbt;
 
        dispatch_once(&once, ^{
-               rb_tree_init(&rbtree, &ops);
+               rb_tree_init(&rbt, &ops);
        });
 
-       return &rbtree;
+       return &rbt;
 }
 
 
@@ -124,7 +112,7 @@ _reach_requests_rbt_queue()
        static dispatch_queue_t q;
 
        dispatch_once(&once, ^{
-               q = dispatch_queue_create(REACH_SERVICE_NAME ".rbt", NULL);
+               q = dispatch_queue_create(REACH_SERVICE_NAME ".requests.rbt", NULL);
        });
 
        return q;
@@ -161,14 +149,13 @@ _reach_request_add(SCNetworkReachabilityRef target)
        uint64_t        target_id       = (uintptr_t)target;
 
        dispatch_sync(_reach_requests_rbt_queue(), ^{
-               struct rb_node          *rbn;
-
-               rbn = rb_tree_find_node(_reach_requests_rbt(), &target_id);
-               if (rbn == NULL) {
-                       reach_request_t *request;
+               rb_tree_t       *rbt    = _reach_requests_rbt();
+               reach_request_t *request;
 
+               request = rb_tree_find_node(rbt, &target_id);
+               if (request == NULL) {
                        request = _reach_request_create(target);
-                       if (request == NULL || !rb_tree_insert_node(_reach_requests_rbt(), &request->rbn)) {
+                       if (request == NULL || !rb_tree_insert_node(rbt, request)) {
                                __builtin_trap();
                        }
                }
@@ -184,17 +171,17 @@ _reach_request_remove(SCNetworkReachabilityRef target)
        uint64_t        target_id       = (uintptr_t)target;
 
        dispatch_sync(_reach_requests_rbt_queue(), ^{           // FIXME ?? use dispatch_async?
-               struct rb_node          *rbn;
-               struct rb_tree          *rbtree = _reach_requests_rbt();
-
-               rbn = rb_tree_find_node(rbtree, &target_id);
-               if (rbn != NULL) {
-                       reach_request_t *request        = RBNODE_TO_REACH_REQUEST(rbn);
+               rb_tree_t       *rbt    = _reach_requests_rbt();
+               reach_request_t *request;
 
-                       rb_tree_remove_node(rbtree, rbn);
+               request = rb_tree_find_node(rbt, &target_id);
+               if (request != NULL) {
+                       rb_tree_remove_node(rbt, request);
                        _reach_request_release(request);
                }
        });
+
+       return;
 }
 
 
@@ -204,12 +191,12 @@ _reach_request_copy_target(uint64_t target_id)
        __block SCNetworkReachabilityRef        target  = NULL;
 
        dispatch_sync(_reach_requests_rbt_queue(), ^{
-               struct rb_node  *rbn;
+               rb_tree_t       *rbt    = _reach_requests_rbt();
+               reach_request_t *request;
 
-               rbn = rb_tree_find_node(_reach_requests_rbt(), &target_id);
-               if (rbn != NULL) {
-                       // handle the [async] reply
-                       target = (SCNetworkReachabilityRef)(uintptr_t)target_id;
+               request = rb_tree_find_node(rbt, &target_id);
+               if (request != NULL) {
+                       target = request->target;
                        CFRetain(target);
                }
        });
@@ -233,7 +220,7 @@ handle_reachability_status(SCNetworkReachabilityRef target, xpc_object_t dict)
 //             log_xpc_object("  status", dict);
        }
 
-       __SCNetworkReachabilityPerformNoLock(target);
+       __SCNetworkReachabilityPerformConcurrent(target);
 
        return;
 }
@@ -284,6 +271,11 @@ static xpc_connection_t
 _reach_connection_create()
 {
        xpc_connection_t                c;
+#if    !TARGET_IPHONE_SIMULATOR
+       const uint64_t          flags   =       XPC_CONNECTION_MACH_SERVICE_PRIVILEGED;
+#else  // !TARGET_IPHONE_SIMULATOR
+       const uint64_t          flags   =       0;
+#endif // !TARGET_IPHONE_SIMULATOR
        const char                      *name;
        dispatch_queue_t                q       = _reach_xpc_queue();
 
@@ -293,9 +285,7 @@ _reach_connection_create()
                name = REACH_SERVICE_NAME;
        }
 
-       c = xpc_connection_create_mach_service(name,
-                                              q,
-                                              XPC_CONNECTION_MACH_SERVICE_PRIVILEGED);
+       c = xpc_connection_create_mach_service(name, q, flags);
 
        xpc_connection_set_event_handler(c, ^(xpc_object_t xobj) {
                xpc_type_t      type;
@@ -316,14 +306,18 @@ _reach_connection_create()
 
                        target = _reach_request_copy_target(target_id);
                        if (target == NULL) {
-                               SCLog(TRUE, LOG_ERR,
-                                     CFSTR("received unexpected target [ID] from SCNetworkReachability server"));
-                               log_xpc_object("  reply", xobj);
+//                             SCLog(TRUE, LOG_ERR,
+//                                   CFSTR("received unexpected target [ID] from SCNetworkReachability server"));
+//                             log_xpc_object("  reply", xobj);
                                return;
                        }
 
-                       handle_async_notification(target, xobj);
-                       CFRelease(target);
+                       xpc_retain(xobj);
+                       dispatch_async(__SCNetworkReachability_concurrent_queue(), ^{
+                               handle_async_notification(target, xobj);
+                               CFRelease(target);
+                               xpc_release(xobj);
+                       });
 
                } else if (type == XPC_TYPE_ERROR) {
                        if (xobj == XPC_ERROR_CONNECTION_INVALID) {
@@ -403,7 +397,7 @@ add_proc_name(xpc_object_t reqdict)
 
 
 static void
-_reach_server_target_reconnect(xpc_connection_t connection, SCNetworkReachabilityRef target);
+_reach_server_target_reconnect(xpc_connection_t connection, SCNetworkReachabilityRef target, Boolean disconnect);
 
 
 static Boolean
@@ -427,11 +421,6 @@ _reach_server_target_add(xpc_connection_t connection, SCNetworkReachabilityRef t
                                          REACH_TARGET_NAME,
                                          targetPrivate->name);
        }
-       if (targetPrivate->serv != NULL) {
-               xpc_dictionary_set_string(reqdict,
-                                         REACH_TARGET_SERV,
-                                         targetPrivate->serv);
-       }
        if (targetPrivate->localAddress != NULL) {
                xpc_dictionary_set_data(reqdict,
                                        REACH_TARGET_LOCAL_ADDR,
@@ -444,12 +433,6 @@ _reach_server_target_add(xpc_connection_t connection, SCNetworkReachabilityRef t
                                        targetPrivate->remoteAddress,
                                        targetPrivate->remoteAddress->sa_len);
        }
-       if (bcmp(&targetPrivate->hints, &hints0, sizeof(struct addrinfo)) != 0) {
-               xpc_dictionary_set_data(reqdict,
-                                       REACH_TARGET_HINTS,
-                                       &targetPrivate->hints,
-                                       sizeof(targetPrivate->hints));
-       }
        if (targetPrivate->if_index != 0) {
                xpc_dictionary_set_int64(reqdict,
                                         REACH_TARGET_IF_INDEX,
@@ -470,6 +453,7 @@ _reach_server_target_add(xpc_connection_t connection, SCNetworkReachabilityRef t
        }
 
 
+
        // add the target [ID]
        xpc_dictionary_set_uint64(reqdict, REACH_CLIENT_TARGET_ID, (uintptr_t)target);
 
@@ -549,9 +533,9 @@ _reach_server_target_remove(xpc_connection_t connection, SCNetworkReachabilityRe
                                        ok = TRUE;
                                        break;
                                case REACH_REQUEST_REPLY_UNKNOWN :
-                                       SCLog(TRUE, LOG_DEBUG,
-                                             CFSTR("reach target %p: SCNetworkReachability server failure, no need to remove"),
-                                             target);
+                                       // target not known by the server (most likely due to a
+                                       // SCNetworkReachability server failure), no need to
+                                       // remove.
                                        ok = TRUE;
                                        break;
                                default : {
@@ -619,9 +603,9 @@ _reach_server_target_schedule(xpc_connection_t connection, SCNetworkReachability
                                        ok = TRUE;
                                        break;
                                case REACH_REQUEST_REPLY_UNKNOWN :
-                                       SCLog(TRUE, LOG_DEBUG,
-                                             CFSTR("reach target %p: SCNetworkReachability server failure, retry schedule"),
-                                             target);
+                                       // target not known by the server (most likely due to a
+                                       // SCNetworkReachability server failure), re-establish
+                                       // and retry scheduling.
                                        retry = TRUE;
                                        break;
                                default : {
@@ -655,7 +639,7 @@ _reach_server_target_schedule(xpc_connection_t connection, SCNetworkReachability
 
        if (retry) {
                // reconnect
-               _reach_server_target_reconnect(connection, target);
+               _reach_server_target_reconnect(connection, target, FALSE);
 
                // and retry
                retry = FALSE;
@@ -671,8 +655,9 @@ static void
 _reach_reply_set_reachability(SCNetworkReachabilityRef target,
                              xpc_object_t              reply)
 {
-       char                            *if_name;
-       size_t                          len             = 0;
+       char    *if_name;
+       size_t  len             = 0;
+
        SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
 
        targetPrivate->serverInfo.cycle = xpc_dictionary_get_uint64(reply,
@@ -702,20 +687,20 @@ _reach_reply_set_reachability(SCNetworkReachabilityRef    target,
        if (targetPrivate->type == reachabilityTypeName) {
                xpc_object_t            addresses;
 
-               if (targetPrivate->resolvedAddress != NULL) {
-                       CFRelease(targetPrivate->resolvedAddress);
-                       targetPrivate->resolvedAddress = NULL;
+               if (targetPrivate->resolvedAddresses != NULL) {
+                       CFRelease(targetPrivate->resolvedAddresses);
+                       targetPrivate->resolvedAddresses = NULL;
                }
 
-               targetPrivate->resolvedAddressError = xpc_dictionary_get_int64(reply,
-                                                                              REACH_STATUS_RESOLVED_ADDRESS_ERROR);
+               targetPrivate->resolvedError = xpc_dictionary_get_int64(reply,
+                                                                       REACH_STATUS_RESOLVED_ERROR);
 
-               addresses = xpc_dictionary_get_value(reply, REACH_STATUS_RESOLVED_ADDRESS);
+               addresses = xpc_dictionary_get_value(reply, REACH_STATUS_RESOLVED_ADDRESSES);
                if ((addresses != NULL) && (xpc_get_type(addresses) != XPC_TYPE_ARRAY)) {
                        addresses = NULL;
                }
 
-               if ((targetPrivate->resolvedAddressError == 0) && (addresses != NULL)) {
+               if ((targetPrivate->resolvedError == NETDB_SUCCESS) && (addresses != NULL)) {
                        int                     i;
                        int                     n;
                        CFMutableArrayRef       newAddresses;
@@ -734,10 +719,10 @@ _reach_reply_set_reachability(SCNetworkReachabilityRef    target,
                                CFRelease(newAddress);
                        }
 
-                       targetPrivate->resolvedAddress = newAddresses;
+                       targetPrivate->resolvedAddresses = newAddresses;
                } else {
                        /* save the error associated with the attempt to resolve the name */
-                       targetPrivate->resolvedAddress = CFRetain(kCFNull);
+                       targetPrivate->resolvedAddresses = CFRetain(kCFNull);
                }
                targetPrivate->needResolve = FALSE;
        }
@@ -746,8 +731,7 @@ _reach_reply_set_reachability(SCNetworkReachabilityRef      target,
 }
 
 
-__private_extern__
-Boolean
+static Boolean
 _reach_server_target_status(xpc_connection_t connection, SCNetworkReachabilityRef target)
 {
        Boolean                         ok              = FALSE;
@@ -791,9 +775,9 @@ _reach_server_target_status(xpc_connection_t connection, SCNetworkReachabilityRe
                                        ok = TRUE;
                                        break;
                                case REACH_REQUEST_REPLY_UNKNOWN :
-                                       SCLog(TRUE, LOG_DEBUG,
-                                             CFSTR("reach target %p: SCNetworkReachability server failure, retry status"),
-                                             target);
+                                       // target not known by the server (most likely due to a
+                                       // SCNetworkReachability server failure), re-establish
+                                       // and retry status.
                                        retry = TRUE;
                                        break;
                                default :
@@ -844,7 +828,7 @@ _reach_server_target_status(xpc_connection_t connection, SCNetworkReachabilityRe
 
        if (retry) {
                // reconnect
-               _reach_server_target_reconnect(connection, target);
+               _reach_server_target_reconnect(connection, target, FALSE);
 
                // and retry
                retry = FALSE;
@@ -862,6 +846,7 @@ _reach_server_target_unschedule(xpc_connection_t connection, SCNetworkReachabili
        Boolean                         ok              = FALSE;
        xpc_object_t                    reply;
        xpc_object_t                    reqdict;
+       Boolean                         retry           = FALSE;
        SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
 
        // create message
@@ -887,19 +872,16 @@ _reach_server_target_unschedule(xpc_connection_t connection, SCNetworkReachabili
                                        ok = TRUE;
                                        break;
                                case REACH_REQUEST_REPLY_UNKNOWN :
-                                       SCLog(TRUE, LOG_DEBUG,
-                                             CFSTR("reach target %p: SCNetworkReachability server failure, no need to unschedule"),
-                                             target);
+                                       // target not known by the server (most likely due to a
+                                       // SCNetworkReachability server failure), re-establish
+                                       // but no need to unschedule.
+                                       retry = TRUE;
                                        break;
                                default :
                                        SCLog(TRUE, LOG_INFO, CFSTR("%s  target unschedule failed"),
                                              targetPrivate->log_prefix);
                                        log_xpc_object("  reply", reply);
                        }
-
-                       if (ok) {
-                               CFRelease(target);
-                       }
                } else if ((type == XPC_TYPE_ERROR) && (reply == XPC_ERROR_CONNECTION_INVALID)) {
                        SCLog(TRUE, LOG_ERR,
                              CFSTR("SCNetworkReachability server not available"));
@@ -907,9 +889,9 @@ _reach_server_target_unschedule(xpc_connection_t connection, SCNetworkReachabili
                        ok = TRUE;
                } else if ((type == XPC_TYPE_ERROR) && (reply == XPC_ERROR_CONNECTION_INTERRUPTED)) {
                        SCLog(TRUE, LOG_DEBUG,
-                             CFSTR("reach target %p: SCNetworkReachability server failure, no need to unschedule"),
+                             CFSTR("reach target %p: SCNetworkReachability server failure, re-establish (but do not re-schedule)"),
                              target);
-                       ok = TRUE;
+                       retry = TRUE;
                } else {
                        SCLog(TRUE, LOG_ERR,
                              CFSTR("reach target %p: _targetUnschedule with unexpected reply"),
@@ -920,6 +902,17 @@ _reach_server_target_unschedule(xpc_connection_t connection, SCNetworkReachabili
                xpc_release(reply);
        }
 
+       if (retry) {
+               // reconnect
+               targetPrivate->serverScheduled = FALSE;
+               _reach_server_target_reconnect(connection, target, FALSE);
+               ok = TRUE;
+       }
+
+       if (ok) {
+               CFRelease(target);
+       }
+
        xpc_release(reqdict);
        return ok;
 }
@@ -930,7 +923,7 @@ _reach_server_target_unschedule(xpc_connection_t connection, SCNetworkReachabili
 
 
 static void
-_reach_server_target_reconnect(xpc_connection_t connection, SCNetworkReachabilityRef target)
+_reach_server_target_reconnect(xpc_connection_t connection, SCNetworkReachabilityRef target, Boolean disconnect)
 {
        Boolean                         ok;
        SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
@@ -940,8 +933,17 @@ _reach_server_target_reconnect(xpc_connection_t connection, SCNetworkReachabilit
                return;
        }
 
-       // server has been restarted
-       targetPrivate->cycle = 0;
+       if (disconnect) {
+               // if we should first disconnect (unschedule, remove)
+               if (targetPrivate->serverScheduled) {
+                       (void) _reach_server_target_unschedule(connection, target);
+               }
+
+               (void) _reach_server_target_remove(connection, target);
+       } else {
+               // server has been restarted
+               targetPrivate->cycle = 0;
+       }
 
        // re-associate with server
        ok = _reach_server_target_add(connection, target);
@@ -962,8 +964,11 @@ _reach_server_target_reconnect(xpc_connection_t connection, SCNetworkReachabilit
                return;
        }
 
-       // .. and update our status
-       __SCNetworkReachabilityPerformNoLock(target);
+       // For addresses, update our status now.  For names, queries will
+       // be updated with a callback
+       if (targetPrivate->type != reachabilityTypeName) {
+               __SCNetworkReachabilityPerform(target);
+       }
 
        return;
 }
@@ -972,26 +977,20 @@ _reach_server_target_reconnect(xpc_connection_t connection, SCNetworkReachabilit
 static void
 _reach_connection_reconnect(xpc_connection_t connection)
 {
-       dispatch_queue_t        q;
-
-       q = _reach_requests_rbt_queue();
-       dispatch_sync(q, ^{
-               struct rb_node          *rbn;
-               struct rb_tree          *rbt;
+       dispatch_sync(_reach_requests_rbt_queue(), ^{
+               rb_tree_t       *rbt    = _reach_requests_rbt();
+               reach_request_t *request;
 
-               rbt = _reach_requests_rbt();
-               rbn = rb_tree_iterate(rbt, NULL, RB_DIR_RIGHT);
-               for ( ; rbn != NULL ; rbn = rb_tree_iterate(rbt, rbn, RB_DIR_LEFT)) {
-                       reach_request_t                 *rbt_request;
+               RB_TREE_FOREACH(request, rbt) {
                        SCNetworkReachabilityRef        target;
 
-                       rbt_request = RBNODE_TO_REACH_REQUEST(rbn);
-
-                       target = rbt_request->target;
+                       xpc_retain(connection);
+                       target = request->target;
                        CFRetain(target);
                        dispatch_async(__SCNetworkReachability_concurrent_queue(), ^{
-                               _reach_server_target_reconnect(connection, target);
+                               _reach_server_target_reconnect(connection, target, FALSE);
                                CFRelease(target);
+                               xpc_release(connection);
                        });
                }
        });
@@ -1183,4 +1182,6 @@ __SCNetworkReachabilityServer_targetUnschedule(SCNetworkReachabilityRef target)
        return ok;
 }
 
+
+
 #endif // HAVE_REACHABILITY_SERVER
index d9dfe2cdd36cec6897980e2bd8b1796819e4d981..8527f32f1a235dc57937637947aeb05995b46a80 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012 Apple Inc. All rights reserved.
+ * Copyright (c) 2011-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -35,8 +35,7 @@
 #include <dispatch/private.h>
 #include <xpc/xpc.h>
 #include <xpc/private.h>
-
-#include "rb.h"
+#include <sys/rbtree.h>
 
 
 #pragma mark -
@@ -264,18 +263,18 @@ _target_reply_add_reachability(SCNetworkReachabilityRef target,
                                  REACH_STATUS_SLEEPING,
                                  targetPrivate->info.sleeping);
        if (targetPrivate->type == reachabilityTypeName) {
-               if (isA_CFArray(targetPrivate->resolvedAddress)) {
+               if (isA_CFArray(targetPrivate->resolvedAddresses)) {
                        xpc_object_t    addresses;
                        CFIndex         i;
                        CFIndex         n;
 
                        addresses = xpc_array_create(NULL, 0);
 
-                       n = CFArrayGetCount(targetPrivate->resolvedAddress);
+                       n = CFArrayGetCount(targetPrivate->resolvedAddresses);
                        for (i = 0; i < n; i++) {
                                CFDataRef       address;
 
-                               address = CFArrayGetValueAtIndex(targetPrivate->resolvedAddress, i);
+                               address = CFArrayGetValueAtIndex(targetPrivate->resolvedAddresses, i);
                                xpc_array_set_data(addresses,
                                                   XPC_ARRAY_APPEND,
                                                   CFDataGetBytePtr(address),
@@ -283,13 +282,13 @@ _target_reply_add_reachability(SCNetworkReachabilityRef target,
                        }
 
                        xpc_dictionary_set_value(reply,
-                                                REACH_STATUS_RESOLVED_ADDRESS,
+                                                REACH_STATUS_RESOLVED_ADDRESSES,
                                                 addresses);
                        xpc_release(addresses);
                }
                xpc_dictionary_set_int64(reply,
-                                        REACH_STATUS_RESOLVED_ADDRESS_ERROR,
-                                        targetPrivate->resolvedAddressError);
+                                        REACH_STATUS_RESOLVED_ERROR,
+                                        targetPrivate->resolvedError);
        }
 
        MUTEX_UNLOCK(&targetPrivate->lock);
@@ -458,6 +457,7 @@ _target_watcher_remove(SCNetworkReachabilityRef     target,
                              connection,
                              target,
                              target_id);
+                       ok = FALSE;
                        return;
                }
 
@@ -469,11 +469,11 @@ _target_watcher_remove(SCNetworkReachabilityRef   target,
                              target,
                              target_id);
                        CFRelease(key);
+                       ok = FALSE;
                        return;
                }
 
                CFDictionaryRemoveValue(targetPrivate->serverWatchers, key);
-               xpc_release(connection);
                CFRelease(key);
 
                n = CFDictionaryGetCount(targetPrivate->serverWatchers);
@@ -502,8 +502,15 @@ _target_watcher_remove(SCNetworkReachabilityRef    target,
                        }
 
                        // no more watchers, flags are no longer valid
-                       (void) _SC_ATOMIC_CMPXCHG(&targetPrivate->serverInfoValid, TRUE, FALSE);
+                       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;
@@ -515,7 +522,7 @@ _target_watcher_remove(SCNetworkReachabilityRef     target,
 
 
 typedef struct {
-       struct rb_node          rbn;
+       rb_node_t               rbn;
        xpc_connection_t        connection;
        pid_t                   pid;
        const char              *proc_name;
@@ -523,56 +530,54 @@ typedef struct {
 } reach_client_t;
 
 
-#define RBNODE_TO_REACH_CLIENT(node) \
-       ((reach_client_t *)((uintptr_t)node - offsetof(reach_client_t, rbn)))
-
-
 static int
-_rbt_compare_transaction_nodes(const struct rb_node *n1, const struct rb_node *n2)
+_rbt_compare_transaction_nodes(void *context, const void *n1, const void *n2)
 {
-       uint64_t        a = (uintptr_t)RBNODE_TO_REACH_CLIENT(n1)->connection;
-       uint64_t        b = (uintptr_t)RBNODE_TO_REACH_CLIENT(n2)->connection;
+       uint64_t        a = (uintptr_t)((reach_client_t *)n1)->connection;
+       uint64_t        b = (uintptr_t)((reach_client_t *)n2)->connection;
 
        return (a - b);
 }
 
 
 static int
-_rbt_compare_transaction_key(const struct rb_node *n1, const void *key)
+_rbt_compare_transaction_key(void *context, const void *n1, const void *key)
 {
-       uint64_t        a = (uintptr_t)RBNODE_TO_REACH_CLIENT(n1)->connection;
+       uint64_t        a = (uintptr_t)((reach_client_t *)n1)->connection;
        uint64_t        b = *(uintptr_t *)key;
 
        return (a - b);
 }
 
 
-static struct rb_tree *
+static rb_tree_t *
 _reach_clients_rbt()
 {
        static dispatch_once_t          once;
-       static const struct rb_tree_ops ops = {
+       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 struct rb_tree           rbtree;
+       static rb_tree_t                rbt;
 
        dispatch_once(&once, ^{
-               rb_tree_init(&rbtree, &ops);
+               rb_tree_init(&rbt, &ops);
        });
 
-       return &rbtree;
+       return &rbt;
 }
 
 
 static dispatch_queue_t
-_reach_connection_queue()
+_reach_clients_rbt_queue()
 {
        static dispatch_once_t  once;
        static dispatch_queue_t q;
 
        dispatch_once(&once, ^{
-               q = dispatch_queue_create(REACH_SERVICE_NAME ".connection", NULL);
+               q = dispatch_queue_create(REACH_SERVICE_NAME ".clients.rbt", NULL);
        });
 
        return q;
@@ -623,13 +628,16 @@ _reach_client_remove_target(const void *key, const void *value, void *context)
                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(targetPrivate->serverWatchers, watchers, NULL);
+                       CFDictionaryGetKeysAndValues(serverWatchers, watchers, NULL);
 
                        for (i = 0; i < n; i++) {
                                CFDataRef               key;
@@ -649,6 +657,8 @@ _reach_client_remove_target(const void *key, const void *value, void *context)
                        if (watchers != watchers_q) {
                                CFAllocatorDeallocate(NULL, watchers);
                        }
+
+                       CFRelease(serverWatchers);
                }
        }
 
@@ -664,27 +674,27 @@ _reach_client_remove_target(const void *key, const void *value, void *context)
 static void
 _reach_client_remove(xpc_connection_t connection)
 {
-       struct rb_tree  *rbtree = _reach_clients_rbt();
-       struct rb_node  *rbn;
+       uint64_t        connection_id   = (uintptr_t)connection;
 
-       rbn = rb_tree_find_node(rbtree, &connection);
-       if (rbn != NULL) {
+       dispatch_sync(_reach_clients_rbt_queue(), ^{
                reach_client_t  *client;
+               rb_tree_t       *rbt    = _reach_clients_rbt();
 
-               client = RBNODE_TO_REACH_CLIENT(rbn);
-
-               // remove any remaining target references (for this client)
-               my_CFDictionaryApplyFunction(client->targets,
-                                            _reach_client_remove_target,
-                                            (void *)connection);
+               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(rbtree, rbn);
-               _reach_client_release(client);
-       } else {
-               SCLog(TRUE, LOG_ERR,
-                     CFSTR("<%p> _reach_client_remove: unexpected client"),
-                     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;
 }
@@ -751,6 +761,21 @@ _client_target_remove(reach_client_t *client, uint64_t target_id)
 #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
  *
@@ -791,7 +816,8 @@ _reach_changed(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags
         */
        if (_SC_ATOMIC_CMPXCHG(&targetPrivate->serverInfoValid, FALSE, TRUE)) {
                if (S_debug) {
-                       SCLog(TRUE, LOG_INFO, CFSTR("  flags are now \"valid\""));
+                       SCLog(TRUE, LOG_INFO, CFSTR("%s  flags are now \"valid\""),
+                             targetPrivate->log_prefix);
                }
        }
 
@@ -828,7 +854,7 @@ _reach_changed(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags
 
                connection = xpc_retain(watcher_key->connection);
                target_id  = watcher_key->target_id;
-               dispatch_async(_reach_connection_queue(), ^{
+               dispatch_async(_reach_server_queue(), ^{
                        xpc_object_t    reply;
 
                        // create our [async] notification
@@ -903,12 +929,10 @@ static void
 target_add(reach_client_t *client, xpc_object_t request)
 {
        const char                              *name;
-       const char                              *serv;
        const struct sockaddr                   *localAddress;
        struct sockaddr_storage                 localAddress0;
        const struct sockaddr                   *remoteAddress;
        struct sockaddr_storage                 remoteAddress0;
-       const struct addrinfo                   *hints;
        int64_t                                 if_index;
        const char                              *if_name        = NULL;
        bool                                    onDemandBypass  = FALSE;
@@ -962,12 +986,6 @@ target_add(reach_client_t *client, xpc_object_t request)
                CC_SHA1_Update(&ctx, name, strlen(name));
        }
 
-       serv = xpc_dictionary_get_string(request, REACH_TARGET_SERV);
-       if (serv != NULL) {
-               CC_SHA1_Update(&ctx, REACH_TARGET_SERV, sizeof(REACH_TARGET_SERV));
-               CC_SHA1_Update(&ctx, serv, strlen(serv));
-       }
-
        localAddress = xpc_dictionary_get_data(request, REACH_TARGET_LOCAL_ADDR, &len);
        if (localAddress != NULL) {
                if ((len == localAddress->sa_len) && (len <= sizeof(struct sockaddr_storage))) {
@@ -996,19 +1014,6 @@ target_add(reach_client_t *client, xpc_object_t request)
                }
        }
 
-       hints = xpc_dictionary_get_data(request, REACH_TARGET_HINTS, &len);
-       if (hints != NULL) {
-               if (len == sizeof(struct addrinfo)) {
-                       CC_SHA1_Update(&ctx, REACH_TARGET_HINTS, sizeof(REACH_TARGET_HINTS));
-                       CC_SHA1_Update(&ctx, hints, len);
-               } else {
-                       xpc_dictionary_set_string(reply,
-                                                 REACH_REQUEST_REPLY_DETAIL,
-                                                 "hints: 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);
@@ -1018,6 +1023,7 @@ target_add(reach_client_t *client, xpc_object_t request)
                }
        }
 
+
        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));
@@ -1057,11 +1063,6 @@ target_add(reach_client_t *client, xpc_object_t request)
                                CFDictionarySetValue(options, kSCNetworkReachabilityOptionNodeName, str);
                                CFRelease(str);
                        }
-                       if (serv != NULL) {
-                               str = CFStringCreateWithCString(NULL, serv, kCFStringEncodingUTF8);
-                               CFDictionarySetValue(options, kSCNetworkReachabilityOptionServName, str);
-                               CFRelease(str);
-                       }
                        if (localAddress != NULL) {
                                data = CFDataCreate(NULL, (const UInt8 *)&localAddress0, localAddress0.ss_len);
                                CFDictionarySetValue(options, kSCNetworkReachabilityOptionLocalAddress, data);
@@ -1072,11 +1073,6 @@ target_add(reach_client_t *client, xpc_object_t request)
                                CFDictionarySetValue(options, kSCNetworkReachabilityOptionRemoteAddress, data);
                                CFRelease(data);
                        }
-                       if (hints != NULL) {
-                               data = CFDataCreate(NULL, (const UInt8 *)hints, sizeof(struct addrinfo));
-                               CFDictionarySetValue(options, kSCNetworkReachabilityOptionHints, data);
-                               CFRelease(data);
-                       }
                        if (onDemandBypass) {
                                CFDictionarySetValue(options,
                                                     kSCNetworkReachabilityOptionConnectionOnDemandBypass,
@@ -1269,10 +1265,15 @@ target_schedule(reach_client_t *client, xpc_object_t request)
 
        // enable monitoring
        ok = _target_watcher_add(target, client->connection, target_id);
-       if (ok) {
-               status = REACH_REQUEST_REPLY_OK;
+       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);
@@ -1353,19 +1354,33 @@ target_status(reach_client_t *client, xpc_object_t request)
                if (scheduled) {
                        /*
                         * The client "scheduled" this target.  As such, we
-                        * know that this an async query and that we only
+                        * 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 (targetPrivate->type != reachabilityTypeName) {
+                               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], %@"),
+                                     CFSTR("<%p>   reply [scheduled%s], %@"),
                                      client->connection,
+                                     targetPrivate->serverInfoValid ? "/valid" : "",
                                      str);
                                CFRelease(str);
                        }
@@ -1373,7 +1388,7 @@ target_status(reach_client_t *client, xpc_object_t request)
                        /*
                         * The client has NOT "scheduled" this target.  As
                         * such, we know that this is a sync query and that
-                        * must return "current" flags.
+                        * we must return "current" flags.
                         */
                        if (targetPrivate->scheduled && targetPrivate->serverInfoValid) {
                                /*
@@ -1397,7 +1412,7 @@ target_status(reach_client_t *client, xpc_object_t request)
                                dispatch_group_t        group;
 
                                /*
-                                * The server target has NOT been "scheduled" (or
+                                * 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
@@ -1407,7 +1422,7 @@ target_status(reach_client_t *client, xpc_object_t request)
                                reply_now = FALSE;
 
                                group = _target_group(target);
-                               if (_SC_ATOMIC_INC(&targetPrivate->serverQueryActive) == 0) {
+                               if (_SC_ATOMIC_INC(&targetPrivate->serverSyncQueryActive) == 0) {
                                        CFRetain(target);
                                        dispatch_group_async(group, _server_concurrent_queue(), ^{
                                                SCNetworkReachabilityFlags      flags;
@@ -1426,8 +1441,24 @@ target_status(reach_client_t *client, xpc_object_t request)
                                                              SCErrorString(SCError()));
                                                }
 
-                                               // flags are now available
-                                               n = _SC_ATOMIC_ZERO(&targetPrivate->serverQueryActive);
+                                               /*
+                                                * 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 &&
+                                                   targetPrivate->type != reachabilityTypeName) {
+                                                       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"),
@@ -1504,7 +1535,6 @@ target_status(reach_client_t *client, xpc_object_t request)
 static void
 target_unschedule(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;
@@ -1545,10 +1575,9 @@ target_unschedule(reach_client_t *client, xpc_object_t request)
        }
 
        // disable monitoring
-       ok = _target_watcher_remove(target, client->connection, target_id);
-       if (ok) {
-               status = REACH_REQUEST_REPLY_OK;
-       }
+       _target_watcher_remove(target, client->connection, target_id);
+
+       status = REACH_REQUEST_REPLY_OK;
 
     done :
 
@@ -1568,33 +1597,35 @@ target_unschedule(reach_client_t *client, xpc_object_t request)
 static void
 _snapshot_digest_watcher(const void *key, const void *value, void *context)
 {
-       FILE                            *f              = (FILE *)context;
-       static reach_client_t           no_client       = {
+       __block reach_client_t  *client         = NULL;
+       FILE                    *f              = (FILE *)context;
+       static reach_client_t   no_client       = {
                .pid = 0,
                .proc_name = "?",
        };
-       struct rb_node                  *rbn;
-       reach_client_t                  *rbt_client;
-       reach_watcher_key_t             *watcher_key;
-       reach_watcher_val_t             *watcher_val;
+       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);
 
-       rbn = rb_tree_find_node(_reach_clients_rbt(), &watcher_key->connection);
-       if (rbn == NULL) {
-               rbn = &no_client.rbn;
-       }
+       dispatch_sync(_reach_clients_rbt_queue(), ^{
+               uint64_t        connection_id   = (uintptr_t)watcher_key->connection;
+               rb_tree_t       *rbt            = _reach_clients_rbt();
 
-       rbt_client = RBNODE_TO_REACH_CLIENT(rbn);
+               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,
-               rbt_client->proc_name,
-               rbt_client->pid,
+               client->proc_name,
+               client->pid,
                watcher_val->n_changes);
 
        return;
@@ -1612,11 +1643,18 @@ _snapshot_digest(const void *key, const void *value, void *context)
 
        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, active = %u, refs = %u\n"),
+               SCPrint(TRUE, f, CFSTR("    valid = %s, async watchers = %u, sync queries = %u, refs = %u\n"),
                        targetPrivate->serverInfoValid ? "Y" : "N",
-                       targetPrivate->serverQueryActive,
+                       nWatchers,
+                       targetPrivate->serverSyncQueryActive,
                        targetPrivate->serverReferences);
 
                SCPrint(TRUE, f, CFSTR("    network %d.%3.3d"),
@@ -1651,7 +1689,7 @@ _snapshot_digest(const void *key, const void *value, void *context)
                }
                SCPrint(TRUE, f, CFSTR("\n"));
 
-               if (targetPrivate->serverWatchers != NULL) {
+               if (nWatchers > 0) {
                        CFDictionaryApplyFunction(targetPrivate->serverWatchers,
                                                  _snapshot_digest_watcher,
                                                  f);
@@ -1689,8 +1727,6 @@ _snapshot(reach_client_t *client, xpc_object_t request)
        FILE                    *f;
        int                     fd;
        Boolean                 ok      = FALSE;
-       struct rb_node          *rbn;
-       struct rb_tree          *rbt;
        xpc_connection_t        remote;
        xpc_object_t            reply;
 
@@ -1738,30 +1774,31 @@ _snapshot(reach_client_t *client, xpc_object_t request)
 
        // provide connection/client info
 
-       SCPrint(TRUE, f, CFSTR("Clients :\n"));
-       rbt = _reach_clients_rbt();
-       rbn = rb_tree_iterate(rbt, NULL, RB_DIR_RIGHT);
-       if (rbn != NULL) {
-               while (rbn != NULL) {
-                       reach_client_t  *rbt_client;
-
-                       rbt_client = RBNODE_TO_REACH_CLIENT(rbn);
-                       SCPrint(TRUE, f,
-                               CFSTR("\n  connection = %p, client = %p, command = %s, pid = %d\n"),
-                               rbt_client->connection,
-                               rbt_client,
-                               rbt_client->proc_name != NULL ? rbt_client->proc_name : "?",
-                               rbt_client->pid);
-                       my_CFDictionaryApplyFunction(rbt_client->targets,
-                                                    _snapshot_target,
-                                                    f);
-
-                       rbn = rb_tree_iterate(rbt, rbn, RB_DIR_LEFT);
+       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"));
                }
-       } else {
-               SCPrint(TRUE, f, CFSTR("  None.\n"));
-       }
-       SCPrint(TRUE, f, CFSTR("\n"));
+
+               SCPrint(TRUE, f, CFSTR("\n"));
+       });
 
        // provide "digest" info
 
@@ -1850,53 +1887,58 @@ process_request(reach_client_t *client, xpc_object_t request)
 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));
        }
 
-       dispatch_sync(_reach_connection_queue(), ^{
-               reach_client_t  *client;
+       client = _reach_client_create(connection);
+       assert(client != NULL);
 
-               client = _reach_client_create(connection);
-               if (client == NULL || !rb_tree_insert_node(_reach_clients_rbt(), &client->rbn)) {
-                       __builtin_trap();
-               }
+       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) {
-                       dispatch_sync(_reach_connection_queue(), ^{
-                               struct rb_node  *rbn;
+                       __block reach_client_t  *client = NULL;
 
-                               rbn = rb_tree_find_node(_reach_clients_rbt(), &connection);
-                               if (rbn != NULL) {
-                                       reach_client_t  *client;
+                       dispatch_sync(_reach_clients_rbt_queue(), ^{
+                               uint64_t        connection_id   = (uintptr_t)connection;
+                               rb_tree_t       *rbt            = _reach_clients_rbt();
 
-                                       // process the request
-                                       client = RBNODE_TO_REACH_CLIENT(rbn);
-                                       process_request(client, xobj);
-                               } else {
-                                       char            *desc;
+                               client = rb_tree_find_node(rbt, &connection_id);
+                       });
 
-                                       SCLog(TRUE, LOG_ERR,
-                                             CFSTR("<%p:%d> unexpected SCNetworkReachability request"),
-                                             connection,
-                                             xpc_connection_get_pid(connection));
+                       if (client != NULL) {
+                               // process the request
+                               process_request(client, xobj);
+                       } else {
+                               char            *desc;
 
-                                       desc = xpc_copy_description(xobj);
-                                       SCLog(TRUE, LOG_ERR,
-                                             CFSTR("  request = %s"),
-                                             desc);
-                                       free(desc);
+                               SCLog(TRUE, LOG_ERR,
+                                     CFSTR("<%p:%d> unexpected SCNetworkReachability request"),
+                                     connection,
+                                     xpc_connection_get_pid(connection));
 
-                                       xpc_connection_cancel(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;
@@ -1911,11 +1953,7 @@ process_new_connection(xpc_connection_t connection)
                                              desc);
                                }
 
-                               xpc_retain(connection);
-                               dispatch_async(_reach_connection_queue(), ^{
-                                       _reach_client_remove(connection);
-                                       xpc_release(connection);
-                               });
+                               _reach_client_remove(connection);
 
                        } else if (xobj == XPC_ERROR_CONNECTION_INTERRUPTED) {
                                SCLog(TRUE, LOG_ERR,
@@ -1958,7 +1996,6 @@ load_SCNetworkReachability(CFBundleRef bundle, Boolean bundleVerbose)
 {
        xpc_connection_t        connection;
        const char              *name;
-       dispatch_queue_t        reach_server_q;
 
        S_debug = bundleVerbose;
 
@@ -1971,19 +2008,13 @@ load_SCNetworkReachability(CFBundleRef bundle, Boolean bundleVerbose)
                                                     &kCFTypeDictionaryKeyCallBacks,
                                                     &kCFTypeDictionaryValueCallBacks);
 
-       /*
-        * create dispatch queue for processing SCNetworkReachability
-        * service requests
-        */
-       reach_server_q = dispatch_queue_create(REACH_SERVICE_NAME, NULL);
-
        // create XPC listener
        name = getenv("REACH_SERVER");
        if (name == NULL) {
                name = REACH_SERVICE_NAME;
        }
        connection = xpc_connection_create_mach_service(name,
-                                                       reach_server_q,
+                                                       _reach_server_queue(),
                                                        XPC_CONNECTION_MACH_SERVICE_LISTENER);
 
        xpc_connection_set_event_handler(connection, ^(xpc_object_t event) {
diff --git a/SystemConfiguration.fproj/reachability/rb.c b/SystemConfiguration.fproj/reachability/rb.c
deleted file mode 100644 (file)
index 21205db..0000000
+++ /dev/null
@@ -1,1323 +0,0 @@
-/* $NetBSD: rb.c,v 1.4 2009/05/19 22:48:19 yamt Exp $ */
-
-/*-
- * Copyright (c) 2001 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Matt Thomas <matt@3am-software.com>.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#if !defined(_KERNEL) && !defined(_STANDALONE)
-#include <sys/types.h>
-#include <stddef.h>
-#include <assert.h>
-#include <stdbool.h>
-#ifdef RBDEBUG
-#define        KASSERT(s)      assert(s)
-#else
-#define KASSERT(s)     do { } while (/*CONSTCOND*/ 0)
-#endif
-#else
-#include <lib/libkern/libkern.h>
-#endif
-
-#ifdef _LIBC
-__weak_alias(rb_tree_init, _rb_tree_init)
-__weak_alias(rb_tree_find_node, _rb_tree_find_node)
-__weak_alias(rb_tree_find_node_geq, _rb_tree_find_node_geq)
-__weak_alias(rb_tree_find_node_leq, _rb_tree_find_node_leq)
-__weak_alias(rb_tree_insert_node, _rb_tree_insert_node)
-__weak_alias(rb_tree_remove_node, _rb_tree_remove_node)
-__weak_alias(rb_tree_iterate, _rb_tree_iterate)
-#ifdef RBDEBUG
-__weak_alias(rb_tree_check, _rb_tree_check)
-__weak_alias(rb_tree_depths, _rb_tree_depths)
-#endif
-
-#define        rb_tree_init            _rb_tree_init
-#define        rb_tree_find_node       _rb_tree_find_node
-#define        rb_tree_find_node_geq   _rb_tree_find_node_geq
-#define        rb_tree_find_node_leq   _rb_tree_find_node_leq
-#define        rb_tree_insert_node     _rb_tree_insert_node
-#define        rb_tree_remove_node     _rb_tree_remove_node
-#define        rb_tree_iterate         _rb_tree_iterate
-#ifdef RBDEBUG
-#define        rb_tree_check           _rb_tree_check
-#define        rb_tree_depths          _rb_tree_depths
-#endif
-#endif
-
-#if defined(RBTEST) || defined(__APPLE__)
-#include "rb.h"
-#else
-#include <sys/rb.h>
-#endif
-
-#ifdef __APPLE__
-#define __predict_true(exp)     __builtin_expect((exp), 1)
-#define __predict_false(exp)    __builtin_expect((exp), 0)
-#endif
-
-static void rb_tree_insert_rebalance(struct rb_tree *, struct rb_node *);
-static void rb_tree_removal_rebalance(struct rb_tree *, struct rb_node *,
-       unsigned int);
-#ifdef RBDEBUG
-static const struct rb_node *rb_tree_iterate_const(const struct rb_tree *,
-       const struct rb_node *, const unsigned int);
-static bool rb_tree_check_node(const struct rb_tree *, const struct rb_node *,
-       const struct rb_node *, bool);
-#else
-#define        rb_tree_check_node(a, b, c, d)  true
-#endif
-
-#define        RB_SENTINEL_NODE        NULL
-
-void
-rb_tree_init(struct rb_tree *rbt, const struct rb_tree_ops *ops)
-{
-       rbt->rbt_ops = ops;
-       *((const struct rb_node **)&rbt->rbt_root) = RB_SENTINEL_NODE;
-       RB_TAILQ_INIT(&rbt->rbt_nodes);
-#ifndef RBSMALL
-       rbt->rbt_minmax[RB_DIR_LEFT] = rbt->rbt_root;   /* minimum node */
-       rbt->rbt_minmax[RB_DIR_RIGHT] = rbt->rbt_root;  /* maximum node */
-#endif
-       rbt->rbt_count = 0;
-#ifdef RBSTATS
-       rbt->rbt_insertions = 0;
-       rbt->rbt_removals = 0;
-       rbt->rbt_insertion_rebalance_calls = 0;
-       rbt->rbt_insertion_rebalance_passes = 0;
-       rbt->rbt_removal_rebalance_calls = 0;
-       rbt->rbt_removal_rebalance_passes = 0;
-#endif
-}
-
-struct rb_node *
-rb_tree_find_node(struct rb_tree *rbt, const void *key)
-{
-       rbto_compare_key_fn compare_key = rbt->rbt_ops->rbto_compare_key;
-       struct rb_node *parent = rbt->rbt_root;
-
-       while (!RB_SENTINEL_P(parent)) {
-               const signed int diff = (*compare_key)(parent, key);
-               if (diff == 0)
-                       return parent;
-               parent = parent->rb_nodes[diff > 0];
-       }
-
-       return NULL;
-}
-
-struct rb_node *
-rb_tree_find_node_geq(struct rb_tree *rbt, const void *key)
-{
-       rbto_compare_key_fn compare_key = rbt->rbt_ops->rbto_compare_key;
-       struct rb_node *parent = rbt->rbt_root;
-       struct rb_node *last = NULL;
-
-       while (!RB_SENTINEL_P(parent)) {
-               const signed int diff = (*compare_key)(parent, key);
-               if (diff == 0)
-                       return parent;
-               if (diff < 0)
-                       last = parent;
-               parent = parent->rb_nodes[diff > 0];
-       }
-
-       return last;
-}
-
-struct rb_node *
-rb_tree_find_node_leq(struct rb_tree *rbt, const void *key)
-{
-       rbto_compare_key_fn compare_key = rbt->rbt_ops->rbto_compare_key;
-       struct rb_node *parent = rbt->rbt_root;
-       struct rb_node *last = NULL;
-
-       while (!RB_SENTINEL_P(parent)) {
-               const signed int diff = (*compare_key)(parent, key);
-               if (diff == 0)
-                       return parent;
-               if (diff > 0)
-                       last = parent;
-               parent = parent->rb_nodes[diff > 0];
-       }
-
-       return last;
-}
-\f
-bool
-rb_tree_insert_node(struct rb_tree *rbt, struct rb_node *self)
-{
-       rbto_compare_nodes_fn compare_nodes = rbt->rbt_ops->rbto_compare_nodes;
-       struct rb_node *parent, *tmp;
-       unsigned int position;
-       bool rebalance;
-
-       RBSTAT_INC(rbt->rbt_insertions);
-
-       tmp = rbt->rbt_root;
-       /*
-        * This is a hack.  Because rbt->rbt_root is just a struct rb_node *,
-        * just like rb_node->rb_nodes[RB_DIR_LEFT], we can use this fact to
-        * avoid a lot of tests for root and know that even at root,
-        * updating RB_FATHER(rb_node)->rb_nodes[RB_POSITION(rb_node)] will
-        * update rbt->rbt_root.
-        */
-       parent = (struct rb_node *)(void *)&rbt->rbt_root;
-       position = RB_DIR_LEFT;
-
-       /*
-        * Find out where to place this new leaf.
-        */
-       while (!RB_SENTINEL_P(tmp)) {
-               const signed int diff = (*compare_nodes)(tmp, self);
-               if (__predict_false(diff == 0)) {
-                       /*
-                        * Node already exists; don't insert.
-                        */
-                       return false;
-               }
-               parent = tmp;
-               position = (diff > 0);
-               tmp = parent->rb_nodes[position];
-       }
-
-#ifdef RBDEBUG
-       {
-               struct rb_node *prev = NULL, *next = NULL;
-
-               if (position == RB_DIR_RIGHT)
-                       prev = parent;
-               else if (tmp != rbt->rbt_root)
-                       next = parent;
-
-               /*
-                * Verify our sequential position
-                */
-               KASSERT(prev == NULL || !RB_SENTINEL_P(prev));
-               KASSERT(next == NULL || !RB_SENTINEL_P(next));
-               if (prev != NULL && next == NULL)
-                       next = TAILQ_NEXT(prev, rb_link);
-               if (prev == NULL && next != NULL)
-                       prev = TAILQ_PREV(next, rb_node_qh, rb_link);
-               KASSERT(prev == NULL || !RB_SENTINEL_P(prev));
-               KASSERT(next == NULL || !RB_SENTINEL_P(next));
-               KASSERT(prev == NULL || (*compare_nodes)(prev, self) > 0);
-               KASSERT(next == NULL || (*compare_nodes)(self, next) > 0);
-       }
-#endif
-
-       /*
-        * Initialize the node and insert as a leaf into the tree.
-        */
-       RB_SET_FATHER(self, parent);
-       RB_SET_POSITION(self, position);
-       if (__predict_false(parent == (struct rb_node *)(void *)&rbt->rbt_root)) {
-               RB_MARK_BLACK(self);            /* root is always black */
-#ifndef RBSMALL
-               rbt->rbt_minmax[RB_DIR_LEFT] = self;
-               rbt->rbt_minmax[RB_DIR_RIGHT] = self;
-#endif
-               rebalance = false;
-       } else {
-               KASSERT(position == RB_DIR_LEFT || position == RB_DIR_RIGHT);
-#ifndef RBSMALL
-               /*
-                * Keep track of the minimum and maximum nodes.  If our
-                * parent is a minmax node and we on their min/max side,
-                * we must be the new min/max node.
-                */
-               if (parent == rbt->rbt_minmax[position])
-                       rbt->rbt_minmax[position] = self;
-#endif /* !RBSMALL */
-               /*
-                * All new nodes are colored red.  We only need to rebalance
-                * if our parent is also red.
-                */
-               RB_MARK_RED(self);
-               rebalance = RB_RED_P(parent);
-       }
-       KASSERT(RB_SENTINEL_P(parent->rb_nodes[position]));
-       self->rb_left = parent->rb_nodes[position];
-       self->rb_right = parent->rb_nodes[position];
-       parent->rb_nodes[position] = self;
-       KASSERT(RB_CHILDLESS_P(self));
-
-       /*
-        * Insert the new node into a sorted list for easy sequential access
-        */
-       rbt->rbt_count++;
-#ifdef RBDEBUG
-       if (RB_ROOT_P(rbt, self)) {
-               RB_TAILQ_INSERT_HEAD(&rbt->rbt_nodes, self, rb_link);
-       } else if (position == RB_DIR_LEFT) {
-               KASSERT((*compare_nodes)(self, RB_FATHER(self)) > 0);
-               RB_TAILQ_INSERT_BEFORE(RB_FATHER(self), self, rb_link);
-       } else {
-               KASSERT((*compare_nodes)(RB_FATHER(self), self) > 0);
-               RB_TAILQ_INSERT_AFTER(&rbt->rbt_nodes, RB_FATHER(self),
-                   self, rb_link);
-       }
-#endif
-       KASSERT(rb_tree_check_node(rbt, self, NULL, !rebalance));
-
-       /*
-        * Rebalance tree after insertion
-        */
-       if (rebalance) {
-               rb_tree_insert_rebalance(rbt, self);
-               KASSERT(rb_tree_check_node(rbt, self, NULL, true));
-       }
-
-       return true;
-}
-\f
-/*
- * Swap the location and colors of 'self' and its child @ which.  The child
- * can not be a sentinel node.  This is our rotation function.  However,
- * since it preserves coloring, it great simplifies both insertion and
- * removal since rotation almost always involves the exchanging of colors
- * as a separate step.
- */
-/*ARGSUSED*/
-static void
-rb_tree_reparent_nodes(struct rb_tree *rbt, struct rb_node *old_father,
-       const unsigned int which)
-{
-       const unsigned int other = which ^ RB_DIR_OTHER;
-       struct rb_node * const grandpa = RB_FATHER(old_father);
-       struct rb_node * const old_child = old_father->rb_nodes[which];
-       struct rb_node * const new_father = old_child;
-       struct rb_node * const new_child = old_father;
-
-       KASSERT(which == RB_DIR_LEFT || which == RB_DIR_RIGHT);
-
-       KASSERT(!RB_SENTINEL_P(old_child));
-       KASSERT(RB_FATHER(old_child) == old_father);
-
-       KASSERT(rb_tree_check_node(rbt, old_father, NULL, false));
-       KASSERT(rb_tree_check_node(rbt, old_child, NULL, false));
-       KASSERT(RB_ROOT_P(rbt, old_father) || rb_tree_check_node(rbt, grandpa, NULL, false));
-
-       /*
-        * Exchange descendant linkages.
-        */
-       grandpa->rb_nodes[RB_POSITION(old_father)] = new_father;
-       new_child->rb_nodes[which] = old_child->rb_nodes[other];
-       new_father->rb_nodes[other] = new_child;
-
-       /*
-        * Update ancestor linkages
-        */
-       RB_SET_FATHER(new_father, grandpa);
-       RB_SET_FATHER(new_child, new_father);
-
-       /*
-        * Exchange properties between new_father and new_child.  The only
-        * change is that new_child's position is now on the other side.
-        */
-#if 0
-       {
-               struct rb_node tmp;
-               tmp.rb_info = 0;
-               RB_COPY_PROPERTIES(&tmp, old_child);
-               RB_COPY_PROPERTIES(new_father, old_father);
-               RB_COPY_PROPERTIES(new_child, &tmp);
-       }
-#else
-       RB_SWAP_PROPERTIES(new_father, new_child);
-#endif
-       RB_SET_POSITION(new_child, other);
-
-       /*
-        * Make sure to reparent the new child to ourself.
-        */
-       if (!RB_SENTINEL_P(new_child->rb_nodes[which])) {
-               RB_SET_FATHER(new_child->rb_nodes[which], new_child);
-               RB_SET_POSITION(new_child->rb_nodes[which], which);
-       }
-
-       KASSERT(rb_tree_check_node(rbt, new_father, NULL, false));
-       KASSERT(rb_tree_check_node(rbt, new_child, NULL, false));
-       KASSERT(RB_ROOT_P(rbt, new_father) || rb_tree_check_node(rbt, grandpa, NULL, false));
-}
-\f
-static void
-rb_tree_insert_rebalance(struct rb_tree *rbt, struct rb_node *self)
-{
-       struct rb_node * father = RB_FATHER(self);
-       struct rb_node * grandpa;
-       struct rb_node * uncle;
-       unsigned int which;
-       unsigned int other;
-
-       KASSERT(!RB_ROOT_P(rbt, self));
-       KASSERT(RB_RED_P(self));
-       KASSERT(RB_RED_P(father));
-       RBSTAT_INC(rbt->rbt_insertion_rebalance_calls);
-
-       for (;;) {
-               KASSERT(!RB_SENTINEL_P(self));
-
-               KASSERT(RB_RED_P(self));
-               KASSERT(RB_RED_P(father));
-               /*
-                * We are red and our parent is red, therefore we must have a
-                * grandfather and he must be black.
-                */
-               grandpa = RB_FATHER(father);
-               KASSERT(RB_BLACK_P(grandpa));
-               KASSERT(RB_DIR_RIGHT == 1 && RB_DIR_LEFT == 0);
-               which = (father == grandpa->rb_right);
-               other = which ^ RB_DIR_OTHER;
-               uncle = grandpa->rb_nodes[other];
-
-               if (RB_BLACK_P(uncle))
-                       break;
-
-               RBSTAT_INC(rbt->rbt_insertion_rebalance_passes);
-               /*
-                * Case 1: our uncle is red
-                *   Simply invert the colors of our parent and
-                *   uncle and make our grandparent red.  And
-                *   then solve the problem up at his level.
-                */
-               RB_MARK_BLACK(uncle);
-               RB_MARK_BLACK(father);
-               if (__predict_false(RB_ROOT_P(rbt, grandpa))) {
-                       /*
-                        * If our grandpa is root, don't bother
-                        * setting him to red, just return.
-                        */
-                       KASSERT(RB_BLACK_P(grandpa));
-                       return;
-               }
-               RB_MARK_RED(grandpa);
-               self = grandpa;
-               father = RB_FATHER(self);
-               KASSERT(RB_RED_P(self));
-               if (RB_BLACK_P(father)) {
-                       /*
-                        * If our greatgrandpa is black, we're done.
-                        */
-                       KASSERT(RB_BLACK_P(rbt->rbt_root));
-                       return;
-               }
-       }
-
-       KASSERT(!RB_ROOT_P(rbt, self));
-       KASSERT(RB_RED_P(self));
-       KASSERT(RB_RED_P(father));
-       KASSERT(RB_BLACK_P(uncle));
-       KASSERT(RB_BLACK_P(grandpa));
-       /*
-        * Case 2&3: our uncle is black.
-        */
-       if (self == father->rb_nodes[other]) {
-               /*
-                * Case 2: we are on the same side as our uncle
-                *   Swap ourselves with our parent so this case
-                *   becomes case 3.  Basically our parent becomes our
-                *   child.
-                */
-               rb_tree_reparent_nodes(rbt, father, other);
-               KASSERT(RB_FATHER(father) == self);
-               KASSERT(self->rb_nodes[which] == father);
-               KASSERT(RB_FATHER(self) == grandpa);
-#ifdef RBDEBUG
-               // only read when RBDEBUG is enabled with KASSERT
-               self = father;
-               father = RB_FATHER(self);
-#endif
-       }
-       KASSERT(RB_RED_P(self) && RB_RED_P(father));
-       KASSERT(grandpa->rb_nodes[which] == father);
-       /*
-        * Case 3: we are opposite a child of a black uncle.
-        *   Swap our parent and grandparent.  Since our grandfather
-        *   is black, our father will become black and our new sibling
-        *   (former grandparent) will become red.
-        */
-       rb_tree_reparent_nodes(rbt, grandpa, which);
-       KASSERT(RB_FATHER(self) == father);
-       KASSERT(RB_FATHER(self)->rb_nodes[RB_POSITION(self) ^ RB_DIR_OTHER] == grandpa);
-       KASSERT(RB_RED_P(self));
-       KASSERT(RB_BLACK_P(father));
-       KASSERT(RB_RED_P(grandpa));
-
-       /*
-        * Final step: Set the root to black.
-        */
-       RB_MARK_BLACK(rbt->rbt_root);
-}
-\f
-static void
-rb_tree_prune_node(struct rb_tree *rbt, struct rb_node *self, bool rebalance)
-{
-       const unsigned int which = RB_POSITION(self);
-       struct rb_node *father = RB_FATHER(self);
-       const bool was_root = RB_ROOT_P(rbt, self);
-
-       KASSERT(rebalance || (RB_ROOT_P(rbt, self) || RB_RED_P(self)));
-       KASSERT(!rebalance || RB_BLACK_P(self));
-       KASSERT(RB_CHILDLESS_P(self));
-       KASSERT(rb_tree_check_node(rbt, self, NULL, false));
-
-       /*
-        * Since we are childless, we know that self->rb_left is pointing
-        * to the sentinel node.
-        */
-       father->rb_nodes[which] = self->rb_left;
-
-       /*
-        * Remove ourselves from the node list, decrement the count,
-        * and update min/max.
-        */
-       RB_TAILQ_REMOVE(&rbt->rbt_nodes, self, rb_link);
-       rbt->rbt_count--;
-#ifndef RBSMALL
-       if (__predict_false(rbt->rbt_minmax[RB_POSITION(self)] == self)) {
-               rbt->rbt_minmax[RB_POSITION(self)] = father;
-               /*
-                * When removing the root, rbt->rbt_minmax[RB_DIR_LEFT] is
-                * updated automatically, but we also need to update
-                * rbt->rbt_minmax[RB_DIR_RIGHT];
-                */
-               if (__predict_false(was_root)) {
-                       rbt->rbt_minmax[RB_DIR_RIGHT] = father;
-               }
-       }
-       RB_SET_FATHER(self, NULL);
-#endif
-
-       /*
-        * Rebalance if requested.
-        */
-       if (rebalance)
-               rb_tree_removal_rebalance(rbt, father, which);
-       KASSERT(was_root || rb_tree_check_node(rbt, father, NULL, true));
-}
-\f
-/*
- * When deleting an interior node
- */
-static void
-rb_tree_swap_prune_and_rebalance(struct rb_tree *rbt, struct rb_node *self,
-       struct rb_node *standin)
-{
-       const unsigned int standin_which = RB_POSITION(standin);
-       unsigned int standin_other = standin_which ^ RB_DIR_OTHER;
-       struct rb_node *standin_son;
-       struct rb_node *standin_father = RB_FATHER(standin);
-       bool rebalance = RB_BLACK_P(standin);
-
-       if (standin_father == self) {
-               /*
-                * As a child of self, any childen would be opposite of
-                * our parent.
-                */
-               KASSERT(RB_SENTINEL_P(standin->rb_nodes[standin_other]));
-               standin_son = standin->rb_nodes[standin_which];
-       } else {
-               /*
-                * Since we aren't a child of self, any childen would be
-                * on the same side as our parent.
-                */
-               KASSERT(RB_SENTINEL_P(standin->rb_nodes[standin_which]));
-               standin_son = standin->rb_nodes[standin_other];
-       }
-
-       /*
-        * the node we are removing must have two children.
-        */
-       KASSERT(RB_TWOCHILDREN_P(self));
-       /*
-        * If standin has a child, it must be red.
-        */
-       KASSERT(RB_SENTINEL_P(standin_son) || RB_RED_P(standin_son));
-
-       /*
-        * Verify things are sane.
-        */
-       KASSERT(rb_tree_check_node(rbt, self, NULL, false));
-       KASSERT(rb_tree_check_node(rbt, standin, NULL, false));
-
-       if (__predict_false(RB_RED_P(standin_son))) {
-               /*
-                * We know we have a red child so if we flip it to black
-                * we don't have to rebalance.
-                */
-               KASSERT(rb_tree_check_node(rbt, standin_son, NULL, true));
-               RB_MARK_BLACK(standin_son);
-               rebalance = false;
-
-               if (standin_father == self) {
-                       KASSERT(RB_POSITION(standin_son) == standin_which);
-               } else {
-                       KASSERT(RB_POSITION(standin_son) == standin_other);
-                       /*
-                        * Change the son's parentage to point to his grandpa.
-                        */
-                       RB_SET_FATHER(standin_son, standin_father);
-                       RB_SET_POSITION(standin_son, standin_which);
-               }
-       }
-
-       if (standin_father == self) {
-               /*
-                * If we are about to delete the standin's father, then when
-                * we call rebalance, we need to use ourselves as our father.
-                * Otherwise remember our original father.  Also, sincef we are
-                * our standin's father we only need to reparent the standin's
-                * brother.
-                *
-                * |    R      -->     S    |
-                * |  Q   S    -->   Q   T  |
-                * |        t  -->          |
-                */
-               KASSERT(RB_SENTINEL_P(standin->rb_nodes[standin_other]));
-               KASSERT(!RB_SENTINEL_P(self->rb_nodes[standin_other]));
-               KASSERT(self->rb_nodes[standin_which] == standin);
-               /*
-                * Have our son/standin adopt his brother as his new son.
-                */
-               standin_father = standin;
-       } else {
-               /*
-                * |    R          -->    S       .  |
-                * |   / \  |   T  -->   / \  |  /   |
-                * |  ..... | S    -->  ..... | T    |
-                *
-                * Sever standin's connection to his father.
-                */
-               standin_father->rb_nodes[standin_which] = standin_son;
-               /*
-                * Adopt the far son.
-                */
-               standin->rb_nodes[standin_other] = self->rb_nodes[standin_other];
-               RB_SET_FATHER(standin->rb_nodes[standin_other], standin);
-               KASSERT(RB_POSITION(self->rb_nodes[standin_other]) == standin_other);
-               /*
-                * Use standin_other because we need to preserve standin_which
-                * for the removal_rebalance.
-                */
-               standin_other = standin_which;
-       }
-
-       /*
-        * Move the only remaining son to our standin.  If our standin is our
-        * son, this will be the only son needed to be moved.
-        */
-       KASSERT(standin->rb_nodes[standin_other] != self->rb_nodes[standin_other]);
-       standin->rb_nodes[standin_other] = self->rb_nodes[standin_other];
-       RB_SET_FATHER(standin->rb_nodes[standin_other], standin);
-
-       /*
-        * Now copy the result of self to standin and then replace
-        * self with standin in the tree.
-        */
-       RB_COPY_PROPERTIES(standin, self);
-       RB_SET_FATHER(standin, RB_FATHER(self));
-       RB_FATHER(standin)->rb_nodes[RB_POSITION(standin)] = standin;
-
-       /*
-        * Remove ourselves from the node list, decrement the count,
-        * and update min/max.
-        */
-       RB_TAILQ_REMOVE(&rbt->rbt_nodes, self, rb_link);
-       rbt->rbt_count--;
-#ifndef RBSMALL
-       if (__predict_false(rbt->rbt_minmax[RB_POSITION(self)] == self))
-               rbt->rbt_minmax[RB_POSITION(self)] = RB_FATHER(self);
-       RB_SET_FATHER(self, NULL);
-#endif
-
-       KASSERT(rb_tree_check_node(rbt, standin, NULL, false));
-       KASSERT(RB_FATHER_SENTINEL_P(standin)
-               || rb_tree_check_node(rbt, standin_father, NULL, false));
-       KASSERT(RB_LEFT_SENTINEL_P(standin)
-               || rb_tree_check_node(rbt, standin->rb_left, NULL, false));
-       KASSERT(RB_RIGHT_SENTINEL_P(standin)
-               || rb_tree_check_node(rbt, standin->rb_right, NULL, false));
-
-       if (!rebalance)
-               return;
-
-       rb_tree_removal_rebalance(rbt, standin_father, standin_which);
-       KASSERT(rb_tree_check_node(rbt, standin, NULL, true));
-}
-
-/*
- * We could do this by doing
- *     rb_tree_node_swap(rbt, self, which);
- *     rb_tree_prune_node(rbt, self, false);
- *
- * But it's more efficient to just evalate and recolor the child.
- */
-static void
-rb_tree_prune_blackred_branch(struct rb_tree *rbt, struct rb_node *self,
-       unsigned int which)
-{
-       struct rb_node *father = RB_FATHER(self);
-       struct rb_node *son = self->rb_nodes[which];
-       const bool was_root = RB_ROOT_P(rbt, self);
-
-       KASSERT(which == RB_DIR_LEFT || which == RB_DIR_RIGHT);
-       KASSERT(RB_BLACK_P(self) && RB_RED_P(son));
-       KASSERT(!RB_TWOCHILDREN_P(son));
-       KASSERT(RB_CHILDLESS_P(son));
-       KASSERT(rb_tree_check_node(rbt, self, NULL, false));
-       KASSERT(rb_tree_check_node(rbt, son, NULL, false));
-
-       /*
-        * Remove ourselves from the tree and give our former child our
-        * properties (position, color, root).
-        */
-       RB_COPY_PROPERTIES(son, self);
-       father->rb_nodes[RB_POSITION(son)] = son;
-       RB_SET_FATHER(son, father);
-
-       /*
-        * Remove ourselves from the node list, decrement the count,
-        * and update minmax.
-        */
-       RB_TAILQ_REMOVE(&rbt->rbt_nodes, self, rb_link);
-       rbt->rbt_count--;
-#ifndef RBSMALL
-       if (__predict_false(was_root)) {
-               KASSERT(rbt->rbt_minmax[which] == son);
-               rbt->rbt_minmax[which ^ RB_DIR_OTHER] = son;
-       } else if (rbt->rbt_minmax[RB_POSITION(self)] == self) {
-               rbt->rbt_minmax[RB_POSITION(self)] = son;
-       }
-       RB_SET_FATHER(self, NULL);
-#endif
-
-       KASSERT(was_root || rb_tree_check_node(rbt, father, NULL, true));
-       KASSERT(rb_tree_check_node(rbt, son, NULL, true));
-}
-/*
- *
- */
-void
-rb_tree_remove_node(struct rb_tree *rbt, struct rb_node *self)
-{
-       struct rb_node *standin;
-       unsigned int which;
-
-       KASSERT(!RB_SENTINEL_P(self));
-       RBSTAT_INC(rbt->rbt_removals);
-
-       /*
-        * In the following diagrams, we (the node to be removed) are S.  Red
-        * nodes are lowercase.  T could be either red or black.
-        *
-        * Remember the major axiom of the red-black tree: the number of
-        * black nodes from the root to each leaf is constant across all
-        * leaves, only the number of red nodes varies.
-        *
-        * Thus removing a red leaf doesn't require any other changes to a
-        * red-black tree.  So if we must remove a node, attempt to rearrange
-        * the tree so we can remove a red node.
-        *
-        * The simpliest case is a childless red node or a childless root node:
-        *
-        * |    T  -->    T  |    or    |  R  -->  *  |
-        * |  s    -->  *    |
-        */
-       if (RB_CHILDLESS_P(self)) {
-               const bool rebalance = RB_BLACK_P(self) && !RB_ROOT_P(rbt, self);
-               rb_tree_prune_node(rbt, self, rebalance);
-               return;
-       }
-       KASSERT(!RB_CHILDLESS_P(self));
-       if (!RB_TWOCHILDREN_P(self)) {
-               /*
-                * The next simpliest case is the node we are deleting is
-                * black and has one red child.
-                *
-                * |      T  -->      T  -->      T  |
-                * |    S    -->  R      -->  R      |
-                * |  r      -->    s    -->    *    |
-                */
-               which = RB_LEFT_SENTINEL_P(self) ? RB_DIR_RIGHT : RB_DIR_LEFT;
-               KASSERT(RB_BLACK_P(self));
-               KASSERT(RB_RED_P(self->rb_nodes[which]));
-               KASSERT(RB_CHILDLESS_P(self->rb_nodes[which]));
-               rb_tree_prune_blackred_branch(rbt, self, which);
-               return;
-       }
-       KASSERT(RB_TWOCHILDREN_P(self));
-
-       /*
-        * We invert these because we prefer to remove from the inside of
-        * the tree.
-        */
-       which = RB_POSITION(self) ^ RB_DIR_OTHER;
-
-       /*
-        * Let's find the node closes to us opposite of our parent
-        * Now swap it with ourself, "prune" it, and rebalance, if needed.
-        */
-       standin = rb_tree_iterate(rbt, self, which);
-       rb_tree_swap_prune_and_rebalance(rbt, self, standin);
-}
-
-static void
-rb_tree_removal_rebalance(struct rb_tree *rbt, struct rb_node *parent,
-       unsigned int which)
-{
-       KASSERT(!RB_SENTINEL_P(parent));
-       KASSERT(RB_SENTINEL_P(parent->rb_nodes[which]));
-       KASSERT(which == RB_DIR_LEFT || which == RB_DIR_RIGHT);
-       RBSTAT_INC(rbt->rbt_removal_rebalance_calls);
-
-       while (RB_BLACK_P(parent->rb_nodes[which])) {
-               unsigned int other = which ^ RB_DIR_OTHER;
-               struct rb_node *brother = parent->rb_nodes[other];
-
-               RBSTAT_INC(rbt->rbt_removal_rebalance_passes);
-
-               KASSERT(!RB_SENTINEL_P(brother));
-               /*
-                * For cases 1, 2a, and 2b, our brother's children must
-                * be black and our father must be black
-                */
-               if (RB_BLACK_P(parent)
-                   && RB_BLACK_P(brother->rb_left)
-                   && RB_BLACK_P(brother->rb_right)) {
-                       if (RB_RED_P(brother)) {
-                               /*
-                                * Case 1: Our brother is red, swap its
-                                * position (and colors) with our parent.
-                                * This should now be case 2b (unless C or E
-                                * has a red child which is case 3; thus no
-                                * explicit branch to case 2b).
-                                *
-                                *    B         ->        D
-                                *  A     d     ->    b     E
-                                *      C   E   ->  A   C
-                                */
-                               KASSERT(RB_BLACK_P(parent));
-                               rb_tree_reparent_nodes(rbt, parent, other);
-                               brother = parent->rb_nodes[other];
-                               KASSERT(!RB_SENTINEL_P(brother));
-                               KASSERT(RB_RED_P(parent));
-                               KASSERT(RB_BLACK_P(brother));
-                               KASSERT(rb_tree_check_node(rbt, brother, NULL, false));
-                               KASSERT(rb_tree_check_node(rbt, parent, NULL, false));
-                       } else {
-                               /*
-                                * Both our parent and brother are black.
-                                * Change our brother to red, advance up rank
-                                * and go through the loop again.
-                                *
-                                *    B         ->   *B
-                                * *A     D     ->  A     d
-                                *      C   E   ->      C   E
-                                */
-                               RB_MARK_RED(brother);
-                               KASSERT(RB_BLACK_P(brother->rb_left));
-                               KASSERT(RB_BLACK_P(brother->rb_right));
-                               if (RB_ROOT_P(rbt, parent))
-                                       return; /* root == parent == black */
-                               KASSERT(rb_tree_check_node(rbt, brother, NULL, false));
-                               KASSERT(rb_tree_check_node(rbt, parent, NULL, false));
-                               if (parent != NULL) {
-                                       which = RB_POSITION(parent);
-                                       parent = RB_FATHER(parent);
-                               }
-                               continue;
-                       }
-               }
-               /*
-                * Avoid an else here so that case 2a above can hit either
-                * case 2b, 3, or 4.
-                */
-               if (RB_RED_P(parent)
-                       && (RB_SENTINEL_P(brother)
-                               || (RB_BLACK_P(brother)
-                                       && RB_BLACK_P(brother->rb_left)
-                                       && RB_BLACK_P(brother->rb_right)))) {
-                       KASSERT(RB_RED_P(parent));
-                       KASSERT(RB_BLACK_P(brother));
-                       KASSERT(RB_BLACK_P(brother->rb_left));
-                       KASSERT(RB_BLACK_P(brother->rb_right));
-                       /*
-                        * We are black, our father is red, our brother and
-                        * both nephews are black.  Simply invert/exchange the
-                        * colors of our father and brother (to black and red
-                        * respectively).
-                        *
-                        *      |    f        -->    F        |
-                        *      |  *     B    -->  *     b    |
-                        *      |      N   N  -->      N   N  |
-                        */
-                       RB_MARK_BLACK(parent);
-                       if (!RB_SENTINEL_P(brother)) {
-                               RB_MARK_RED(brother);
-                       }
-                       KASSERT(rb_tree_check_node(rbt, brother, NULL, true));
-                       break;          /* We're done! */
-               } else {
-                       /*
-                        * Our brother must be black and have at least one
-                        * red child (it may have two).
-                        */
-                       KASSERT(RB_BLACK_P(brother));
-                       KASSERT(RB_RED_P(brother->rb_nodes[which]) ||
-                               RB_RED_P(brother->rb_nodes[other]));
-                       if (RB_BLACK_P(brother->rb_nodes[other])) {
-                               /*
-                                * Case 3: our brother is black, our near
-                                * nephew is red, and our far nephew is black.
-                                * Swap our brother with our near nephew.
-                                * This result in a tree that matches case 4.
-                                * (Our father could be red or black).
-                                *
-                                *      |    F      -->    F      |
-                                *      |  x     B  -->  x   B    |
-                                *      |      n    -->        n  |
-                                */
-                               KASSERT(RB_RED_P(brother->rb_nodes[which]));
-                               rb_tree_reparent_nodes(rbt, brother, which);
-                               KASSERT(RB_FATHER(brother) == parent->rb_nodes[other]);
-                               brother = parent->rb_nodes[other];
-                               KASSERT(RB_RED_P(brother->rb_nodes[other]));
-                       }
-                       /*
-                        * Case 4: our brother is black and our far nephew
-                        * is red.  Swap our father and brother locations and
-                        * change our far nephew to black.  (these can be
-                        * done in either order so we change the color first).
-                        * The result is a valid red-black tree and is a
-                        * terminal case.  (again we don't care about the
-                        * father's color)
-                        *
-                        * If the father is red, we will get a red-black-black
-                        * tree:
-                        *      |  f      ->  f      -->    b    |
-                        *      |    B    ->    B    -->  F   N  |
-                        *      |      n  ->      N  -->         |
-                        *
-                        * If the father is black, we will get an all black
-                        * tree:
-                        *      |  F      ->  F      -->    B    |
-                        *      |    B    ->    B    -->  F   N  |
-                        *      |      n  ->      N  -->         |
-                        *
-                        * If we had two red nephews, then after the swap,
-                        * our former father would have a red grandson.
-                        */
-                       KASSERT(RB_BLACK_P(brother));
-                       KASSERT(RB_RED_P(brother->rb_nodes[other]));
-                       RB_MARK_BLACK(brother->rb_nodes[other]);
-                       rb_tree_reparent_nodes(rbt, parent, other);
-                       break;          /* We're done! */
-               }
-       }
-       KASSERT(rb_tree_check_node(rbt, parent, NULL, true));
-}
-
-struct rb_node *
-rb_tree_iterate(struct rb_tree *rbt, struct rb_node *self,
-       const unsigned int direction)
-{
-       const unsigned int other = direction ^ RB_DIR_OTHER;
-       KASSERT(direction == RB_DIR_LEFT || direction == RB_DIR_RIGHT);
-
-       if (self == NULL) {
-#ifndef RBSMALL
-               if (RB_SENTINEL_P(rbt->rbt_root))
-                       return NULL;
-               return rbt->rbt_minmax[direction];
-#else
-               self = rbt->rbt_root;
-               if (RB_SENTINEL_P(self))
-                       return NULL;
-               while (!RB_SENTINEL_P(self->rb_nodes[other]))
-                       self = self->rb_nodes[other];
-               return self;
-#endif /* !RBSMALL */
-       }
-       KASSERT(!RB_SENTINEL_P(self));
-       /*
-        * We can't go any further in this direction.  We proceed up in the
-        * opposite direction until our parent is in direction we want to go.
-        */
-       if (RB_SENTINEL_P(self->rb_nodes[direction])) {
-               while (!RB_ROOT_P(rbt, self)) {
-                       if (other == RB_POSITION(self))
-                               return RB_FATHER(self);
-                       self = RB_FATHER(self);
-               }
-               return NULL;
-       }
-
-       /*
-        * Advance down one in current direction and go down as far as possible
-        * in the opposite direction.
-        */
-       self = self->rb_nodes[direction];
-       KASSERT(!RB_SENTINEL_P(self));
-       while (!RB_SENTINEL_P(self->rb_nodes[other]))
-               self = self->rb_nodes[other];
-       return self;
-}
-
-#ifdef RBDEBUG
-static const struct rb_node *
-rb_tree_iterate_const(const struct rb_tree *rbt, const struct rb_node *self,
-       const unsigned int direction)
-{
-       const unsigned int other = direction ^ RB_DIR_OTHER;
-       KASSERT(direction == RB_DIR_LEFT || direction == RB_DIR_RIGHT);
-
-       if (self == NULL) {
-#ifndef RBSMALL
-               if (RB_SENTINEL_P(rbt->rbt_root))
-                       return NULL;
-               return rbt->rbt_minmax[direction];
-#else
-               self = rbt->rbt_root;
-               if (RB_SENTINEL_P(self))
-                       return NULL;
-               while (!RB_SENTINEL_P(self->rb_nodes[other]))
-                       self = self->rb_nodes[other];
-               return self;
-#endif /* !RBSMALL */
-       }
-       KASSERT(!RB_SENTINEL_P(self));
-       /*
-        * We can't go any further in this direction.  We proceed up in the
-        * opposite direction until our parent is in direction we want to go.
-        */
-       if (RB_SENTINEL_P(self->rb_nodes[direction])) {
-               while (!RB_ROOT_P(rbt, self)) {
-                       if (other == RB_POSITION(self))
-                               return RB_FATHER(self);
-                       self = RB_FATHER(self);
-               }
-               return NULL;
-       }
-
-       /*
-        * Advance down one in current direction and go down as far as possible
-        * in the opposite direction.
-        */
-       self = self->rb_nodes[direction];
-       KASSERT(!RB_SENTINEL_P(self));
-       while (!RB_SENTINEL_P(self->rb_nodes[other]))
-               self = self->rb_nodes[other];
-       return self;
-}
-
-static unsigned int
-rb_tree_count_black(const struct rb_node *self)
-{
-       unsigned int left, right;
-
-       if (RB_SENTINEL_P(self))
-               return 0;
-
-       left = rb_tree_count_black(self->rb_left);
-       right = rb_tree_count_black(self->rb_right);
-
-       KASSERT(left == right);
-
-       return left + RB_BLACK_P(self);
-}
-
-static bool
-rb_tree_check_node(const struct rb_tree *rbt, const struct rb_node *self,
-       const struct rb_node *prev, bool red_check)
-{
-       rbto_compare_nodes_fn compare_nodes = rbt->rbt_ops->rbto_compare_nodes;
-
-       KASSERT(!RB_SENTINEL_P(self));
-       KASSERT(prev == NULL || (*compare_nodes)(prev, self) > 0);
-
-       /*
-        * Verify our relationship to our parent.
-        */
-       if (RB_ROOT_P(rbt, self)) {
-               KASSERT(self == rbt->rbt_root);
-               KASSERT(RB_POSITION(self) == RB_DIR_LEFT);
-               KASSERT(RB_FATHER(self)->rb_nodes[RB_DIR_LEFT] == self);
-               KASSERT(RB_FATHER(self) == (const struct rb_node *) &rbt->rbt_root);
-       } else {
-               KASSERT(self != rbt->rbt_root);
-               KASSERT(!RB_FATHER_SENTINEL_P(self));
-               if (RB_POSITION(self) == RB_DIR_LEFT) {
-                       KASSERT((*compare_nodes)(self, RB_FATHER(self)) > 0);
-                       KASSERT(RB_FATHER(self)->rb_nodes[RB_DIR_LEFT] == self);
-               } else {
-                       KASSERT((*compare_nodes)(self, RB_FATHER(self)) < 0);
-                       KASSERT(RB_FATHER(self)->rb_nodes[RB_DIR_RIGHT] == self);
-               }
-       }
-
-       /*
-        * Verify our position in the linked list against the tree itself.
-        */
-       {
-               const struct rb_node *prev0 = rb_tree_iterate_const(rbt, self, RB_DIR_LEFT);
-               const struct rb_node *next0 = rb_tree_iterate_const(rbt, self, RB_DIR_RIGHT);
-               KASSERT(prev0 == TAILQ_PREV(self, rb_node_qh, rb_link));
-               KASSERT(next0 == TAILQ_NEXT(self, rb_link));
-#ifndef RBSMALL
-               KASSERT(prev0 != NULL || self == rbt->rbt_minmax[RB_DIR_LEFT]);
-               KASSERT(next0 != NULL || self == rbt->rbt_minmax[RB_DIR_RIGHT]);
-#endif
-       }
-
-       /*
-        * The root must be black.
-        * There can never be two adjacent red nodes.
-        */
-       if (red_check) {
-               KASSERT(!RB_ROOT_P(rbt, self) || RB_BLACK_P(self));
-               (void) rb_tree_count_black(self);
-               if (RB_RED_P(self)) {
-                       const struct rb_node *brother;
-                       KASSERT(!RB_ROOT_P(rbt, self));
-                       brother = RB_FATHER(self)->rb_nodes[RB_POSITION(self) ^ RB_DIR_OTHER];
-                       KASSERT(RB_BLACK_P(RB_FATHER(self)));
-                       /*
-                        * I'm red and have no children, then I must either
-                        * have no brother or my brother also be red and
-                        * also have no children.  (black count == 0)
-                        */
-                       KASSERT(!RB_CHILDLESS_P(self)
-                               || RB_SENTINEL_P(brother)
-                               || RB_RED_P(brother)
-                               || RB_CHILDLESS_P(brother));
-                       /*
-                        * If I'm not childless, I must have two children
-                        * and they must be both be black.
-                        */
-                       KASSERT(RB_CHILDLESS_P(self)
-                               || (RB_TWOCHILDREN_P(self)
-                                   && RB_BLACK_P(self->rb_left)
-                                   && RB_BLACK_P(self->rb_right)));
-                       /*
-                        * If I'm not childless, thus I have black children,
-                        * then my brother must either be black or have two
-                        * black children.
-                        */
-                       KASSERT(RB_CHILDLESS_P(self)
-                               || RB_BLACK_P(brother)
-                               || (RB_TWOCHILDREN_P(brother)
-                                   && RB_BLACK_P(brother->rb_left)
-                                   && RB_BLACK_P(brother->rb_right)));
-               } else {
-                       /*
-                        * If I'm black and have one child, that child must
-                        * be red and childless.
-                        */
-                       KASSERT(RB_CHILDLESS_P(self)
-                               || RB_TWOCHILDREN_P(self)
-                               || (!RB_LEFT_SENTINEL_P(self)
-                                   && RB_RIGHT_SENTINEL_P(self)
-                                   && RB_RED_P(self->rb_left)
-                                   && RB_CHILDLESS_P(self->rb_left))
-                               || (!RB_RIGHT_SENTINEL_P(self)
-                                   && RB_LEFT_SENTINEL_P(self)
-                                   && RB_RED_P(self->rb_right)
-                                   && RB_CHILDLESS_P(self->rb_right)));
-
-                       /*
-                        * If I'm a childless black node and my parent is
-                        * black, my 2nd closet relative away from my parent
-                        * is either red or has a red parent or red children.
-                        */
-                       if (!RB_ROOT_P(rbt, self)
-                           && RB_CHILDLESS_P(self)
-                           && RB_BLACK_P(RB_FATHER(self))) {
-                               const unsigned int which = RB_POSITION(self);
-                               const unsigned int other = which ^ RB_DIR_OTHER;
-                               const struct rb_node *relative0, *relative;
-
-                               relative0 = rb_tree_iterate_const(rbt,
-                                   self, other);
-                               KASSERT(relative0 != NULL);
-                               relative = rb_tree_iterate_const(rbt,
-                                   relative0, other);
-                               KASSERT(relative != NULL);
-                               KASSERT(RB_SENTINEL_P(relative->rb_nodes[which]));
-#if 0
-                               KASSERT(RB_RED_P(relative)
-                                       || RB_RED_P(relative->rb_left)
-                                       || RB_RED_P(relative->rb_right)
-                                       || RB_RED_P(RB_FATHER(relative)));
-#endif
-                       }
-               }
-               /*
-                * A grandparent's children must be real nodes and not
-                * sentinels.  First check out grandparent.
-                */
-               KASSERT(RB_ROOT_P(rbt, self)
-                       || RB_ROOT_P(rbt, RB_FATHER(self))
-                       || RB_TWOCHILDREN_P(RB_FATHER(RB_FATHER(self))));
-               /*
-                * If we are have grandchildren on our left, then
-                * we must have a child on our right.
-                */
-               KASSERT(RB_LEFT_SENTINEL_P(self)
-                       || RB_CHILDLESS_P(self->rb_left)
-                       || !RB_RIGHT_SENTINEL_P(self));
-               /*
-                * If we are have grandchildren on our right, then
-                * we must have a child on our left.
-                */
-               KASSERT(RB_RIGHT_SENTINEL_P(self)
-                       || RB_CHILDLESS_P(self->rb_right)
-                       || !RB_LEFT_SENTINEL_P(self));
-
-               /*
-                * If we have a child on the left and it doesn't have two
-                * children make sure we don't have great-great-grandchildren on
-                * the right.
-                */
-               KASSERT(RB_TWOCHILDREN_P(self->rb_left)
-                       || RB_CHILDLESS_P(self->rb_right)
-                       || RB_CHILDLESS_P(self->rb_right->rb_left)
-                       || RB_CHILDLESS_P(self->rb_right->rb_left->rb_left)
-                       || RB_CHILDLESS_P(self->rb_right->rb_left->rb_right)
-                       || RB_CHILDLESS_P(self->rb_right->rb_right)
-                       || RB_CHILDLESS_P(self->rb_right->rb_right->rb_left)
-                       || RB_CHILDLESS_P(self->rb_right->rb_right->rb_right));
-
-               /*
-                * If we have a child on the right and it doesn't have two
-                * children make sure we don't have great-great-grandchildren on
-                * the left.
-                */
-               KASSERT(RB_TWOCHILDREN_P(self->rb_right)
-                       || RB_CHILDLESS_P(self->rb_left)
-                       || RB_CHILDLESS_P(self->rb_left->rb_left)
-                       || RB_CHILDLESS_P(self->rb_left->rb_left->rb_left)
-                       || RB_CHILDLESS_P(self->rb_left->rb_left->rb_right)
-                       || RB_CHILDLESS_P(self->rb_left->rb_right)
-                       || RB_CHILDLESS_P(self->rb_left->rb_right->rb_left)
-                       || RB_CHILDLESS_P(self->rb_left->rb_right->rb_right));
-
-               /*
-                * If we are fully interior node, then our predecessors and
-                * successors must have no children in our direction.
-                */
-               if (RB_TWOCHILDREN_P(self)) {
-                       const struct rb_node *prev0;
-                       const struct rb_node *next0;
-
-                       prev0 = rb_tree_iterate_const(rbt, self, RB_DIR_LEFT);
-                       KASSERT(prev0 != NULL);
-                       KASSERT(RB_RIGHT_SENTINEL_P(prev0));
-
-                       next0 = rb_tree_iterate_const(rbt, self, RB_DIR_RIGHT);
-                       KASSERT(next0 != NULL);
-                       KASSERT(RB_LEFT_SENTINEL_P(next0));
-               }
-       }
-
-       return true;
-}
-
-void
-rb_tree_check(const struct rb_tree *rbt, bool red_check)
-{
-       const struct rb_node *self;
-       const struct rb_node *prev;
-#ifdef RBSTATS
-       unsigned int count = 0;
-#endif
-
-       KASSERT(rbt->rbt_root != NULL);
-       KASSERT(RB_LEFT_P(rbt->rbt_root));
-
-#if defined(RBSTATS) && !defined(RBSMALL)
-       KASSERT(rbt->rbt_count > 1
-           || rbt->rbt_minmax[RB_DIR_LEFT] == rbt->rbt_minmax[RB_DIR_RIGHT]);
-#endif
-
-       prev = NULL;
-       TAILQ_FOREACH(self, &rbt->rbt_nodes, rb_link) {
-               rb_tree_check_node(rbt, self, prev, false);
-#ifdef RBSTATS
-               count++;
-#endif
-       }
-#ifdef RBSTATS
-       KASSERT(rbt->rbt_count == count);
-#endif
-       if (red_check) {
-               KASSERT(RB_BLACK_P(rbt->rbt_root));
-               KASSERT(RB_SENTINEL_P(rbt->rbt_root)
-                       || rb_tree_count_black(rbt->rbt_root));
-
-               /*
-                * The root must be black.
-                * There can never be two adjacent red nodes.
-                */
-               TAILQ_FOREACH(self, &rbt->rbt_nodes, rb_link) {
-                       rb_tree_check_node(rbt, self, NULL, true);
-               }
-       }
-}
-#endif /* RBDEBUG */
-
-#ifdef RBSTATS
-static void
-rb_tree_mark_depth(const struct rb_tree *rbt, const struct rb_node *self,
-       size_t *depths, size_t depth)
-{
-       if (RB_SENTINEL_P(self))
-               return;
-
-       if (RB_TWOCHILDREN_P(self)) {
-               rb_tree_mark_depth(rbt, self->rb_left, depths, depth + 1);
-               rb_tree_mark_depth(rbt, self->rb_right, depths, depth + 1);
-               return;
-       }
-       depths[depth]++;
-       if (!RB_LEFT_SENTINEL_P(self)) {
-               rb_tree_mark_depth(rbt, self->rb_left, depths, depth + 1);
-       }
-       if (!RB_RIGHT_SENTINEL_P(self)) {
-               rb_tree_mark_depth(rbt, self->rb_right, depths, depth + 1);
-       }
-}
-
-void
-rb_tree_depths(const struct rb_tree *rbt, size_t *depths)
-{
-       rb_tree_mark_depth(rbt, rbt->rbt_root, depths, 1);
-}
-#endif /* RBSTATS */
diff --git a/SystemConfiguration.fproj/reachability/rb.h b/SystemConfiguration.fproj/reachability/rb.h
deleted file mode 100644 (file)
index 56f910d..0000000
+++ /dev/null
@@ -1,195 +0,0 @@
-/* $NetBSD: rb.h,v 1.13 2009/08/16 10:57:01 yamt Exp $ */
-
-/*-
- * Copyright (c) 2001 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Matt Thomas <matt@3am-software.com>.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef _SYS_RB_H_
-#define        _SYS_RB_H_
-
-#if defined(_KERNEL) || defined(_STANDALONE)
-#include <sys/types.h>
-#else
-#include <stdbool.h>
-#include <inttypes.h>
-#endif
-#include <sys/queue.h>
-#ifndef __APPLE__
-#include <sys/endian.h>
-#endif
-
-struct rb_node {
-       struct rb_node *rb_nodes[2];
-#define        RB_DIR_LEFT             0
-#define        RB_DIR_RIGHT            1
-#define        RB_DIR_OTHER            1
-#define        rb_left                 rb_nodes[RB_DIR_LEFT]
-#define        rb_right                rb_nodes[RB_DIR_RIGHT]
-
-       /*
-        * rb_info contains the two flags and the parent back pointer.
-        * We put the two flags in the low two bits since we know that
-        * rb_node will have an alignment of 4 or 8 bytes.
-        */
-       uintptr_t rb_info;
-#define        RB_FLAG_POSITION        0x2
-#define        RB_FLAG_RED             0x1
-#define        RB_FLAG_MASK            (RB_FLAG_POSITION|RB_FLAG_RED)
-#define        RB_FATHER(rb) \
-    ((struct rb_node *)((rb)->rb_info & ~RB_FLAG_MASK))
-#define        RB_SET_FATHER(rb, father) \
-    ((void)((rb)->rb_info = (uintptr_t)(father)|((rb)->rb_info & RB_FLAG_MASK)))
-
-#define        RB_SENTINEL_P(rb)       ((rb) == NULL)
-#define        RB_LEFT_SENTINEL_P(rb)  RB_SENTINEL_P((rb)->rb_left)
-#define        RB_RIGHT_SENTINEL_P(rb) RB_SENTINEL_P((rb)->rb_right)
-#define        RB_FATHER_SENTINEL_P(rb) RB_SENTINEL_P(RB_FATHER((rb)))
-#define        RB_CHILDLESS_P(rb) \
-    (RB_SENTINEL_P(rb) || (RB_LEFT_SENTINEL_P(rb) && RB_RIGHT_SENTINEL_P(rb)))
-#define        RB_TWOCHILDREN_P(rb) \
-    (!RB_SENTINEL_P(rb) && !RB_LEFT_SENTINEL_P(rb) && !RB_RIGHT_SENTINEL_P(rb))
-
-#define        RB_POSITION(rb) \
-    (((rb)->rb_info & RB_FLAG_POSITION) ? RB_DIR_RIGHT : RB_DIR_LEFT)
-#define        RB_RIGHT_P(rb)          (RB_POSITION(rb) == RB_DIR_RIGHT)
-#define        RB_LEFT_P(rb)           (RB_POSITION(rb) == RB_DIR_LEFT)
-#define        RB_RED_P(rb)            (!RB_SENTINEL_P(rb) && ((rb)->rb_info & RB_FLAG_RED) != 0)
-#define        RB_BLACK_P(rb)          (RB_SENTINEL_P(rb) || ((rb)->rb_info & RB_FLAG_RED) == 0)
-#define        RB_MARK_RED(rb)         ((void)((rb)->rb_info |= RB_FLAG_RED))
-#define        RB_MARK_BLACK(rb)       ((void)((rb)->rb_info &= ~RB_FLAG_RED))
-#define        RB_INVERT_COLOR(rb)     ((void)((rb)->rb_info ^= RB_FLAG_RED))
-#define        RB_ROOT_P(rbt, rb)      ((rbt)->rbt_root == (rb))
-#define        RB_SET_POSITION(rb, position) \
-    ((void)((position) ? ((rb)->rb_info |= RB_FLAG_POSITION) : \
-    ((rb)->rb_info &= ~RB_FLAG_POSITION)))
-#define        RB_ZERO_PROPERTIES(rb)  ((void)((rb)->rb_info &= ~RB_FLAG_MASK))
-#define        RB_COPY_PROPERTIES(dst, src) \
-    ((void)((dst)->rb_info ^= ((dst)->rb_info ^ (src)->rb_info) & RB_FLAG_MASK))
-#define RB_SWAP_PROPERTIES(a, b) do { \
-    uintptr_t xorinfo = ((a)->rb_info ^ (b)->rb_info) & RB_FLAG_MASK; \
-    (a)->rb_info ^= xorinfo; \
-    (b)->rb_info ^= xorinfo; \
-  } while (/*CONSTCOND*/ 0)
-#ifdef RBDEBUG
-       TAILQ_ENTRY(rb_node) rb_link;
-#endif
-};
-
-#define RB_TREE_MIN(T) rb_tree_iterate((T), NULL, RB_DIR_LEFT)
-#define RB_TREE_MAX(T) rb_tree_iterate((T), NULL, RB_DIR_RIGHT)
-#define RB_TREE_FOREACH(N, T) \
-    for ((N) = RB_TREE_MIN(T); (N); \
-       (N) = rb_tree_iterate((T), (N), RB_DIR_RIGHT))
-#define RB_TREE_FOREACH_REVERSE(N, T) \
-    for ((N) = RB_TREE_MAX(T); (N); \
-       (N) = rb_tree_iterate((T), (N), RB_DIR_LEFT))
-
-#ifdef RBDEBUG
-TAILQ_HEAD(rb_node_qh, rb_node);
-
-#define        RB_TAILQ_REMOVE(a, b, c)                TAILQ_REMOVE(a, b, c)
-#define        RB_TAILQ_INIT(a)                        TAILQ_INIT(a)
-#define        RB_TAILQ_INSERT_HEAD(a, b, c)           TAILQ_INSERT_HEAD(a, b, c)
-#define        RB_TAILQ_INSERT_BEFORE(a, b, c)         TAILQ_INSERT_BEFORE(a, b, c)
-#define        RB_TAILQ_INSERT_AFTER(a, b, c, d)       TAILQ_INSERT_AFTER(a, b, c, d)
-#else
-#define        RB_TAILQ_REMOVE(a, b, c)                do { } while (/*CONSTCOND*/0)
-#define        RB_TAILQ_INIT(a)                        do { } while (/*CONSTCOND*/0)
-#define        RB_TAILQ_INSERT_HEAD(a, b, c)           do { } while (/*CONSTCOND*/0)
-#define        RB_TAILQ_INSERT_BEFORE(a, b, c)         do { } while (/*CONSTCOND*/0)
-#define        RB_TAILQ_INSERT_AFTER(a, b, c, d)       do { } while (/*CONSTCOND*/0)
-#endif /* RBDEBUG */
-
-/*
- * rbto_compare_nodes_fn:
- *     return a positive value if the first node < the second node.
- *     return a negative value if the first node > the second node.
- *     return 0 if they are considered same.
- *
- * rbto_compare_key_fn:
- *     return a positive value if the node < the key.
- *     return a negative value if the node > the key.
- *     return 0 if they are considered same.
- */
-
-typedef signed int (*const rbto_compare_nodes_fn)(const struct rb_node *,
-    const struct rb_node *);
-typedef signed int (*const rbto_compare_key_fn)(const struct rb_node *,
-    const void *);
-
-struct rb_tree_ops {
-       rbto_compare_nodes_fn rbto_compare_nodes;
-       rbto_compare_key_fn rbto_compare_key;
-};
-
-struct rb_tree {
-       struct rb_node *rbt_root;
-       const struct rb_tree_ops *rbt_ops;
-       struct rb_node *rbt_minmax[2];
-#ifdef RBDEBUG
-       struct rb_node_qh rbt_nodes;
-#endif
-       unsigned int rbt_count;
-#ifdef RBSTATS
-       unsigned int rbt_insertions;
-       unsigned int rbt_removals;
-       unsigned int rbt_insertion_rebalance_calls;
-       unsigned int rbt_insertion_rebalance_passes;
-       unsigned int rbt_removal_rebalance_calls;
-       unsigned int rbt_removal_rebalance_passes;
-#endif
-};
-
-#ifdef RBSTATS
-#define        RBSTAT_INC(v)   ((void)((v)++))
-#define        RBSTAT_DEC(v)   ((void)((v)--))
-#else
-#define        RBSTAT_INC(v)   do { } while (/*CONSTCOND*/0)
-#define        RBSTAT_DEC(v)   do { } while (/*CONSTCOND*/0)
-#endif
-
-void   rb_tree_init(struct rb_tree *, const struct rb_tree_ops *);
-bool   rb_tree_insert_node(struct rb_tree *, struct rb_node *);
-struct rb_node *
-       rb_tree_find_node(struct rb_tree *, const void *);
-struct rb_node *
-       rb_tree_find_node_geq(struct rb_tree *, const void *);
-struct rb_node *
-       rb_tree_find_node_leq(struct rb_tree *, const void *);
-void   rb_tree_remove_node(struct rb_tree *, struct rb_node *);
-struct rb_node *
-       rb_tree_iterate(struct rb_tree *, struct rb_node *, const unsigned int);
-#ifdef RBDEBUG
-void   rb_tree_check(const struct rb_tree *, bool);
-#endif
-#ifdef RBSTATS
-void   rb_tree_depths(const struct rb_tree *, size_t *);
-#endif
-
-#endif /* _SYS_RB_H_*/
diff --git a/SystemConfiguration.fproj/scprefs_observer.c b/SystemConfiguration.fproj/scprefs_observer.c
new file mode 100644 (file)
index 0000000..6d9a074
--- /dev/null
@@ -0,0 +1,333 @@
+/*
+ * Copyright (c) 2012, 2013 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 <CommonCrypto/CommonDigest.h>
+#include <dirent.h>
+#include <notify.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <SystemConfiguration/SCPrivate.h>
+#include <SystemConfiguration/scprefs_observer.h>
+
+#pragma mark -
+#pragma mark Utils
+
+static void
+iterate_dir(const char *d_name, const char *f_name,
+           CC_SHA1_CTX *ctxP, Boolean *found)
+{
+       DIR *dir;
+       struct dirent * dp;
+
+       dir = opendir(d_name);
+
+       if (dir == NULL) {
+               /* if directory path does not exist */
+               return;
+       }
+
+       while ((dp = readdir(dir)) != NULL) {
+               char            full_path[MAXPATHLEN];
+               struct stat     s;
+
+               if ((strcmp(dp->d_name, ".") == 0) ||
+                   (strcmp(dp->d_name, "..") == 0)) {
+                       continue;
+               }
+
+               /* check path */
+               snprintf(full_path, sizeof(full_path), "%s/%s", d_name, dp->d_name);
+               if (stat(full_path, &s) == 0) {
+                       if (S_ISDIR(s.st_mode)) {
+                               // if sub-directory, iterate
+                               iterate_dir(full_path, f_name, ctxP, found);
+                       } else if (strcmp(f_name, dp->d_name) == 0) {
+                               /*
+                                * if this is the requested file, include
+                                * the path and last modification time in
+                                * the digest
+                               */
+                               CC_SHA1_Update(ctxP, full_path, strlen(full_path));
+                               CC_SHA1_Update(ctxP,
+                                              (void *)&s.st_mtimespec.tv_sec,
+                                              sizeof(s.st_mtimespec.tv_sec));
+                               *found = TRUE;
+                       }
+               }
+       }
+       closedir(dir);
+       return;
+}
+
+static CFDataRef
+build_digest(const char *top_dir, const char *file)
+{
+       unsigned char   bytes[CC_SHA1_DIGEST_LENGTH];
+       CC_SHA1_CTX     ctx;
+       CFDataRef       digest = NULL;
+       Boolean         found = FALSE;
+
+       CC_SHA1_Init(&ctx);
+       iterate_dir(top_dir, file, &ctx, &found);
+       CC_SHA1_Final(bytes, &ctx);
+       if (found == TRUE) {
+               digest = CFDataCreate(NULL, bytes, sizeof(bytes));
+       }
+       return (digest);
+}
+
+#pragma mark -
+#pragma mark perfs_observer Private
+
+struct _scprefs_observer_t {
+       _scprefs_observer_type                  type;
+       dispatch_block_t                        block;
+       CFDataRef                               digest;
+       SLIST_ENTRY(_scprefs_observer_t)        next;
+       dispatch_queue_t                        queue;
+       char                                    file[0];
+};
+
+#define MOBILE_PREFERENCES_PATH "/var/mobile/Library/Preferences"
+static const char *
+prefs_observer_get_prefs_path(scprefs_observer_t observer)
+{
+       switch (observer->type) {
+#if    !TARGET_OS_IPHONE
+       case scprefs_observer_type_mcx:
+               return ("/Library/Managed Preferences");
+#else  // !TARGET_OS_IPHONE
+       case scprefs_observer_type_global:
+               return ("/Library/Managed Preferences");
+       case scprefs_observer_type_profile:
+               return MOBILE_PREFERENCES_PATH;
+#endif // !TARGET_OS_IPHONE
+       default:
+               return (NULL);
+       }
+}
+
+/*
+ * Iterate through all of the directories and subdirectories.
+ * If the file within those directories has changed,
+ * then generate the notification.
+ */
+static Boolean
+has_changed(scprefs_observer_t  observer) {
+       Boolean         changed;
+       CFDataRef       digest = NULL;
+       const char *    starting_path;
+
+       starting_path = prefs_observer_get_prefs_path(observer);
+
+       digest = build_digest(starting_path, observer->file);
+
+       /* compare old vs. new digest */
+       changed = _SC_CFEqual(digest, observer->digest)?FALSE:TRUE;
+
+       /* save the digest */
+       if (observer->digest != NULL) {
+               CFRelease(observer->digest);
+       }
+
+       observer->digest = digest;
+
+       SCLog(_sc_verbose, LOG_NOTICE, CFSTR("The following file: %s, %s \n"),
+             observer->file, (changed)?"has changed":"has not changed");
+       return (changed);
+}
+
+static dispatch_queue_t
+prefs_observer_queue;
+
+/* This holds the list of the observers */
+static SLIST_HEAD(mylist, _scprefs_observer_t) head;
+
+static void
+prefs_observer_release(scprefs_observer_t observer)
+{
+       SLIST_REMOVE(&head, observer, _scprefs_observer_t, next);
+
+       /* Now free the observer */
+       if (observer->digest != NULL) {
+               CFRelease(observer->digest);
+       }
+
+       free(observer);
+}
+
+static void
+prefs_observer_handle_notifications()
+{
+       scprefs_observer_t observer;
+
+       SCLog(_sc_verbose, LOG_NOTICE, CFSTR("PrefsObserver Notification received \n"));
+
+       SLIST_FOREACH(observer, &head, next) {
+               /* if the preferences plist has changed,
+                * called the block */
+               if (has_changed(observer)) {
+                       dispatch_async(observer->queue, observer->block);
+               }
+       }
+}
+
+#define PREFS_OBSERVER_KEY "com.apple.ManagedConfiguration.profileListChanged"
+static void
+_prefs_observer_init()
+{
+       static int token;
+
+       prefs_observer_queue = dispatch_queue_create("com.apple.SystemConfiguration.SCPreferencesObserver", NULL);
+
+       SLIST_INIT(&head);
+
+       notify_register_dispatch(PREFS_OBSERVER_KEY,
+                            &token,
+                            prefs_observer_queue,
+                            ^(int token) { prefs_observer_handle_notifications(); });
+}
+
+static scprefs_observer_t
+prefs_observer_priv_create(_scprefs_observer_type type,
+                          const char *plist_name,
+                          dispatch_queue_t queue,
+                          dispatch_block_t block)
+{
+       scprefs_observer_t observer;
+       int path_buflen;
+
+       path_buflen = strlen(plist_name) + 1;
+
+       observer = (scprefs_observer_t)malloc(sizeof(struct _scprefs_observer_t) + path_buflen);
+       bzero((void *)observer, sizeof(struct _scprefs_observer_t));
+
+       /* Create the observer */
+       observer->type = type;
+       strlcpy(observer->file, plist_name, path_buflen);
+
+       observer->queue = queue;
+       observer->block = Block_copy(block);
+
+       return (observer);
+}
+
+#pragma mark -
+#pragma mark perfs_observer Public SPI
+scprefs_observer_t
+_scprefs_observer_watch(_scprefs_observer_type type, const char *plist_name,
+                          dispatch_queue_t queue, dispatch_block_t block)
+{
+       scprefs_observer_t elem;
+       static dispatch_once_t initialized;
+
+       dispatch_once(&initialized, ^{ _prefs_observer_init(); } );
+
+       elem = prefs_observer_priv_create(type, plist_name, queue, block);
+       SCLog(_sc_verbose, LOG_NOTICE, CFSTR("Created a new element to watch for %s \n"),
+             elem->file);
+
+       dispatch_sync(prefs_observer_queue,
+                     ^{
+                         /* Enqueue the request */
+                         SLIST_INSERT_HEAD(&head, elem, next);
+                     });
+       return (elem);
+}
+
+/* This will cancel/deregister the given watcher.  This will be synchronized on the
+ * internally created queue. */
+void
+_scprefs_observer_cancel(scprefs_observer_t observer)
+{
+       dispatch_sync(prefs_observer_queue,
+                     ^{ prefs_observer_release((scprefs_observer_t)observer); });
+
+}
+
+#pragma mark -
+
+#ifdef TEST_MAIN
+int main()
+{
+       int random = 1;
+
+       _sc_verbose = 1;
+
+       dispatch_queue_t q = dispatch_queue_create("com.apple.SystemConfiguration.PrefsObserver.mainQ", NULL);
+
+       dispatch_queue_t q1 = dispatch_queue_create("com.apple.SystemConfiguration.PrefsObserver.testQ1", NULL);
+
+       dispatch_block_t b1 = ^{
+       printf("Block 1 executed \n");
+       };
+
+       dispatch_queue_t q2 = dispatch_queue_create("com.apple.SystemConfiguration.PrefsObserver.testQ2", NULL);
+       dispatch_block_t b2  = ^{
+       printf("Block 2 executed \n");
+       };
+
+       dispatch_queue_t q3 =  dispatch_queue_create("com.apple.SystemConfiguration.PrefsObserver.testQ2", NULL);
+
+       dispatch_block_t b3 = ^{
+       printf("Block 3 executed \n");
+       };
+
+       __block scprefs_observer_t observer1 = _scprefs_observer_watch(scprefs_observer_type_mcx, "com.apple.SystemConfiguration", q1, b1);
+
+       __block scprefs_observer_t observer2 = _scprefs_observer_watch(scprefs_observer_type_mcx, "foo", q2, b2);
+
+       __block scprefs_observer_t observer3 = _scprefs_observer_watch(scprefs_observer_type_mcx, "bar", q3, b3);
+
+       __block scprefs_observer_t observer = NULL;
+
+       while (1) {
+       switch (random % 3)
+       {
+           case 0:
+               dispatch_async(q, ^{ _SC_prefs_observer_cancel(observer1);
+                                    observer1 = NULL; });
+               dispatch_async(q, ^{ if (observer != NULL)  _SC_prefs_observer_cancel(observer);
+                                    observer = _SC_prefs_observer_watch(SC_prefs_observer_type_mcx,
+                                                                        "test", q2, b2); } );
+               dispatch_sync( q, ^{observer1 = observer; });
+               sleep(random);
+               break;
+           case 1:
+               dispatch_async(q, ^{ _SC_prefs_observer_cancel(observer2); });
+               dispatch_async(q, ^{ if (observer != NULL)  _SC_prefs_observer_cancel(observer); });
+               dispatch_sync( q, ^{observer = _SC_prefs_observer_watch(SC_prefs_observer_type_mcx,
+                                                                       "test", q2, b2); } );
+               sleep(random);
+               break;
+           case 2:
+               sleep (random);
+           default:
+               break;
+       }
+       random++;
+       }
+       dispatch_main();
+}
+#endif
diff --git a/SystemConfiguration.fproj/scprefs_observer.h b/SystemConfiguration.fproj/scprefs_observer.h
new file mode 100644 (file)
index 0000000..a80ef47
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2012, 2013 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@
+ */
+
+#ifndef _SCPREFS_OBSERVER_H
+#define _SCPREFS_OBSERVER_H
+
+typedef enum {
+#if    !TARGET_OS_IPHONE
+               scprefs_observer_type_mcx       = 1,
+#else  // !TARGET_OS_IPHONE
+               scprefs_observer_type_global    = 2,
+               scprefs_observer_type_profile   = 3,
+#endif // !TARGET_OS_IPHONE
+} _scprefs_observer_type;
+
+typedef struct _scprefs_observer_t * scprefs_observer_t;
+
+/*!
+ @function prefs_observer_watch
+ @discussion Sends a notification to interested configuration agents
+ when a particular preference file has changed.
+ @param type - the type of preference (MCX on OSX, Global/Profiles on iOS) to watch.
+ @param plist - the name of the plist file to watch.
+ @param queue - the queue to be called back on.
+ @param block - the block to be called back on.
+ @result Returns the created preferences observer
+ */
+scprefs_observer_t
+_scprefs_observer_watch(_scprefs_observer_type type, const char *plist_name,
+                       dispatch_queue_t queue, dispatch_block_t block);
+
+/*!
+ @function prefs_observer_watch
+ @discussion Cancells/deregisters the given preferences watcher.
+ @param observer - the watcher to be cancelled.
+ */
+void
+_scprefs_observer_cancel(scprefs_observer_t observer);
+
+#endif /* _SCPREFS_OBSERVER_H */
index 862125b9468b5e484ca033bb6ddd32ca97a38699..c1c1104fd1855926aec455ad0e72f9654ee08906 100755 (executable)
@@ -24,6 +24,7 @@ sub clean_API {
 
        $api_new = $DO_SPLIT ? $api : clean_INC($api);
        $api_new =~ s/(__MAC)_\w+\/\*SPI\*\//\1_NA/g;
+       $api_new =~ s/#define\t__AVAILABILITY_INTERNAL__.*FUTURE.*\/\*SPI\*\/\n//;
        $api_new =~ s/(__IPHONE)_\w+\/\*SPI\*\//\1_NA/g;
 
        return $api_new;
@@ -35,6 +36,7 @@ sub clean_SPI {
 
        $spi_new = clean_INC($spi);
        $spi_new =~ s/(__MAC_\w+)\/\*SPI\*\//\1/g;
+       $spi_new =~ s/(#define\t__AVAILABILITY_INTERNAL__.*FUTURE.*)\/\*SPI\*\//\1/;
        $spi_new =~ s/(__IPHONE_\w+)\/\*SPI\*\//\1/g;
 
        return $spi_new;
index bb6449735f6e517f474c85d453ea26773458772e..c54f4ba4c05782b9a4441de5f88fb67559a2814b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2001, 2003-2005, 2009, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2003-2005, 2009, 2011, 2012 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -232,21 +232,26 @@ _removeWatcher(CFNumberRef sessionNum, CFStringRef watchedKey)
 }
 
 
+#define N_QUICK        64
+
+
 __private_extern__
 void
 pushNotifications(FILE *_configd_trace)
 {
-       const void                      **sessionsToNotify;
        CFIndex                         notifyCnt;
        int                             server;
-       serverSessionRef                theSession;
+       const void *                    sessionsToNotify_q[N_QUICK];
+       const void **                   sessionsToNotify        = sessionsToNotify_q;
        SCDynamicStorePrivateRef        storePrivate;
+       serverSessionRef                theSession;
 
        if (needsNotification == NULL)
                return;         /* if no sessions need to be kicked */
 
        notifyCnt = CFSetGetCount(needsNotification);
-       sessionsToNotify = malloc(notifyCnt * sizeof(CFNumberRef));
+       if (notifyCnt > (CFIndex)(sizeof(sessionsToNotify_q) / sizeof(CFNumberRef)))
+               sessionsToNotify = CFAllocatorAllocate(NULL, notifyCnt * sizeof(CFNumberRef), 0);
        CFSetGetValues(needsNotification, sessionsToNotify);
        while (--notifyCnt >= 0) {
                (void) CFNumberGetValue(sessionsToNotify[notifyCnt],
@@ -361,7 +366,7 @@ pushNotifications(FILE *_configd_trace)
                        }
               }
        }
-       free(sessionsToNotify);
+       if (sessionsToNotify != sessionsToNotify_q) CFAllocatorDeallocate(NULL, sessionsToNotify);
 
        /*
         * this list of notifications have been posted, wait for some more.
index f532b47a9800698eaee81620037e1b46290a51b5..8f01964bb908fc2b444fd69faaa4bfd873375d91 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2001, 2003, 2004, 2006, 2008, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2003, 2004, 2006, 2008, 2011, 2012 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -134,7 +134,7 @@ _configadd(mach_port_t                      server,
                }
        }
 
-       if (!hasWriteAccess(mySession)) {
+       if (!hasWriteAccess(mySession, key)) {
                *sc_status = kSCStatusAccessError;
                goto done;
        }
index 34e46b36fe1d778715cb939ac735efe405045a04..61729e48fcd1bbe9d617055c800433b7b2dde0be 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2001, 2003, 2004, 2006-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2003, 2004, 2006-2012 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -36,8 +36,6 @@
 #include "configd.h"
 #include "session.h"
 
-#define        N_QUICK 16
-
 static Boolean
 isMySessionKey(CFStringRef sessionKey, CFStringRef key)
 {
index 52db0f86e58f4c020e475b17c08247c9896d26fe..ee85c5ce76d3c9dbb8ccf64be2afb5cec4505585 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2004, 2006, 2008, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2004, 2006, 2008, 2011, 2012 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -109,7 +109,7 @@ _confignotify(mach_port_t           server,
                }
        }
 
-       if (!hasWriteAccess(mySession)) {
+       if (!hasWriteAccess(mySession, key)) {
                *sc_status = kSCStatusAccessError;
                goto done;
        }
index 2d43008f26b9a17f468b9c44da9e8e46f82602f1..eb27106ea92accbac49a5747766e4dbf802b255d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2004, 2006, 2008, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2004, 2006, 2008, 2011, 2012 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -149,7 +149,7 @@ _configremove(mach_port_t           server,
                }
        }
 
-       if (!hasWriteAccess(mySession)) {
+       if (!hasWriteAccess(mySession, key)) {
                *sc_status = kSCStatusAccessError;
                goto done;
        }
index ee05645aa2edc85c7824619f00ad59e1d1457abb..0dd2b41b8ec8d1509d67a2d2d4068b50e471eea4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2004, 2006, 2008, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2004, 2006, 2008, 2011, 2012 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -255,7 +255,7 @@ _configset(mach_port_t                      server,
                }
        }
 
-       if (!hasWriteAccess(mySession)) {
+       if (!hasWriteAccess(mySession, key)) {
                *sc_status = kSCStatusAccessError;
                goto done;
        }
@@ -371,6 +371,8 @@ __SCDynamicStoreSetMultiple(SCDynamicStoreRef store, CFDictionaryRef keysToSet,
        return sc_status;
 }
 
+#define        N_QUICK 32
+
 __private_extern__
 kern_return_t
 _configset_m(mach_port_t               server,
@@ -440,9 +442,65 @@ _configset_m(mach_port_t           server,
                }
        }
 
-       if (!hasWriteAccess(mySession)) {
-               *sc_status = kSCStatusAccessError;
-               goto done;
+       if (dict != NULL) {
+               const void *    keys_q[N_QUICK];
+               const void **   keys    = keys_q;
+               CFIndex         i;
+               CFIndex         n;
+               Boolean         writeOK = TRUE;
+
+               n = CFDictionaryGetCount(dict);
+               if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFStringRef))) {
+                       keys   = CFAllocatorAllocate(NULL, n * sizeof(CFStringRef), 0);
+               }
+               CFDictionaryGetKeysAndValues(dict, keys, NULL);
+               for (i = 0; i < n; i++) {
+                       CFStringRef     key;
+
+                       key = (CFStringRef)keys[i];
+                       if (!hasWriteAccess(mySession, key)) {
+                               writeOK = FALSE;
+                               break;
+                       }
+               }
+               if (keys != keys_q) {
+                       CFAllocatorDeallocate(NULL, keys);
+               }
+
+               if (!writeOK) {
+                       *sc_status = kSCStatusAccessError;
+                       goto done;
+               }
+       }
+
+       if (remove != NULL) {
+               CFIndex i;
+               CFIndex n       = CFArrayGetCount(remove);
+
+               for (i = 0; i < n; i++) {
+                       CFStringRef     key;
+
+                       key = CFArrayGetValueAtIndex(remove, i);
+                       if (!hasWriteAccess(mySession, key)) {
+                               *sc_status = kSCStatusAccessError;
+                               goto done;
+                       }
+               }
+       }
+
+       if (notify != NULL) {
+               CFIndex i;
+               CFIndex n       = CFArrayGetCount(notify);
+
+               for (i = 0; i < n; i++) {
+                       CFStringRef     key;
+
+                       key = CFArrayGetValueAtIndex(notify, i);
+                       if (!hasWriteAccess(mySession, key)) {
+                               *sc_status = kSCStatusAccessError;
+                               goto done;
+                       }
+               }
        }
 
        *sc_status = __SCDynamicStoreSetMultiple(mySession->store, dict, remove, notify);
index bd4a261e328c65d0a8e9f530d5db756cdae92f0e..9c894a570f90fda66180a721f67a8961d89b64dc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2004, 2006, 2008, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2004, 2006, 2008, 2010-2012 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -100,7 +100,7 @@ __SCDynamicStoreRemoveWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boole
 
                /*
                 * We are watching a specific key. As such, update the
-                * store to mark our interest in any changes.
+                * store to remove our interest in any changes.
                 */
                sessionNum = CFNumberCreate(NULL, kCFNumberIntType, &storePrivate->server);
                _removeWatcher(sessionNum, key);
index 33473f19a316b9c0f7ec5b1db77b8e60aa73c69f..e9c87cf0b4a40a291adb7b9d72969d093623fc36 100644 (file)
                <true/>
                <key>com.apple.SystemConfiguration.SCNetworkReachability</key>
                <true/>
+               <key>com.apple.SystemConfiguration.DNSConfiguration</key>
+               <true/>
+               <key>com.apple.SystemConfiguration.NetworkInformation</key>
+               <true/>
        </dict>
        <key>POSIXSpawnType</key>
        <string>Interactive</string>
diff --git a/configd.tproj/com.apple.configd_sim.plist b/configd.tproj/com.apple.configd_sim.plist
new file mode 100644 (file)
index 0000000..39b9c8e
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>EnableTransactions</key>
+       <true/>
+       <key>KeepAlive</key>
+       <true/>
+       <key>Label</key>
+       <string>com.apple.configd_sim</string>
+       <key>MachServices</key>
+       <dict>
+               <key>com.apple.SystemConfiguration.configd_sim</key>
+               <true/>
+               <key>com.apple.SystemConfiguration.SCNetworkReachability_sim</key>
+               <true/>
+               <key>com.apple.SystemConfiguration.DNSConfiguration_sim</key>
+               <true/>
+               <key>com.apple.SystemConfiguration.NetworkInformation_sim</key>
+               <true/>
+       </dict>
+       <key>POSIXSpawnType</key>
+       <string>Interactive</string>
+       <key>ProgramArguments</key>
+       <array>
+               <string>/usr/libexec/configd_sim</string>
+               <string>-d</string>
+       </array>
+       <key>Umask</key>
+       <integer>18</integer>
+</dict>
+</plist>
index f697803fe94e9741ec68f7acb238026758dab4af..9006d7b9ffd7ceecb805508cd77b7380ca067883 100644 (file)
@@ -51,10 +51,10 @@ in the foreground without forking.  This is useful for debugging.
 .It Fl v
 Puts
 .Nm
-into verbose mode.  Displays debugging information about 
+into verbose mode.  Displays debugging information about
 bundles as they are being loaded.
 .It Fl V Ar bundleID
-Turns verbose mode on for the bundle with the specified 
+Turns verbose mode on for the bundle with the specified
 .Ar bundleID .
 .It Fl t Ar bundle-path
 Loads only the bundle specified by
index 0a527297db532ac331af94e5379dda028376bb3d..852c41af6d9c4babc7c354ab295a368436a73e93 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2011, 2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -55,9 +55,9 @@
 #include "configd_server.h"
 #include "plugin_support.h"
 
-#if    TARGET_OS_EMBEDDED && !TARGET_OS_EMBEDDED_OTHER && !defined(DO_NOT_INFORM)
+#if    TARGET_OS_EMBEDDED && !defined(DO_NOT_INFORM)
 #include <CoreFoundation/CFUserNotification.h>
-#endif // TARGET_OS_EMBEDDED && !TARGET_OS_EMBEDDED_OTHER && !defined(DO_NOT_INFORM)
+#endif // TARGET_OS_EMBEDDED && !defined(DO_NOT_INFORM)
 
 __private_extern__
 Boolean        _configd_verbose                = FALSE;        /* TRUE if verbose logging enabled */
@@ -346,15 +346,17 @@ main(int argc, char * const argv[])
 //     argv += optind;
 
        /* check credentials */
+#if    !TARGET_IPHONE_SIMULATOR
        if (getuid() != 0) {
                fprintf(stderr, "%s: permission denied.\n", prog);
                exit (EX_NOPERM);
        }
+#endif // !TARGET_IPHONE_SIMULATOR
 
        /* check if we have been started by launchd */
        vproc_swap_integer(NULL, VPROC_GSK_IS_MANAGED, NULL, &is_launchd_job);
 
-#if    TARGET_OS_EMBEDDED && !TARGET_OS_EMBEDDED_OTHER && !defined(DO_NOT_INFORM)
+#if    TARGET_OS_EMBEDDED && !defined(DO_NOT_INFORM)
        // if launchd job, check to see if we have been restarted
        if (is_launchd_job) {
                int64_t status  = 0;
@@ -379,7 +381,7 @@ main(int argc, char * const argv[])
                        }
                }
        }
-#endif // TARGET_OS_EMBEDDED && !TARGET_OS_EMBEDDED_OTHER && !defined(DO_NOT_INFORM)
+#endif // TARGET_OS_EMBEDDED && !defined(DO_NOT_INFORM)
 
        /* ensure that forked plugins behave */
        if ((testBundle != NULL) && (getenv("__FORKED_PLUGIN__") != NULL)) {
index 99240d50217ec84e06cb3b8d333216d637c2019f..bbbb9c1a63c3547fb244c43e6696e2d7c76000ad 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2011, 2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -34,6 +34,7 @@
  * - initial revision
  */
 
+#include <TargetConditionals.h>
 #include <sysexits.h>
 #include <unistd.h>
 #include <sys/types.h>
 extern struct mig_subsystem    _config_subsystem;
 extern boolean_t               config_server(mach_msg_header_t *, mach_msg_header_t *);
 
-#include "shared_dns_info_types.h"
-#include "dnsinfo_server.h"
-
-/* MiG generated externals and functions */
-extern struct mig_subsystem    _shared_dns_info_subsystem;
-extern boolean_t               shared_dns_info_server(mach_msg_header_t *, mach_msg_header_t *);
-
 /* configd server port (for new session requests) */
 static CFMachPortRef           configd_port            = NULL;
 
@@ -72,14 +66,6 @@ config_demux(mach_msg_header_t *request, mach_msg_header_t *reply)
                return TRUE;
        }
 
-       /*
-        * (attempt to) process DNS configuration requests.
-        */
-       processed = shared_dns_info_server(request, reply);
-       if (processed) {
-               return TRUE;
-       }
-
        /*
         * (attempt to) process (NO MORE SENDERS) notification messages.
         */
@@ -121,9 +107,6 @@ configdCallback(CFMachPortRef port, void *msg, CFIndex size, void *info)
        if (bufSize == 0) {
                // get max size for MiG reply buffers
                bufSize = _config_subsystem.maxsize;
-               if (_shared_dns_info_subsystem.maxsize > bufSize) {
-                       bufSize = _shared_dns_info_subsystem.maxsize;
-               }
 
                // check if our on-the-stack reply buffer will be big enough
                if (bufSize > sizeof(bufReply_q)) {
@@ -240,7 +223,8 @@ server_init()
                        exit (EX_UNAVAILABLE);
                default :
                        SCLog(TRUE, LOG_ERR,
-                             CFSTR("server_init bootstrap_check_in() failed: %s"),
+                             CFSTR("server_init bootstrap_check_in(..., '%s', ...) failed: %s"),
+                             service_name,
                              bootstrap_strerror(status));
                        exit (EX_UNAVAILABLE);
        }
@@ -268,7 +252,6 @@ server_shutdown()
        if (configd_port != NULL) {
                mach_port_t     service_port    = CFMachPortGetPort(configd_port);
 
-               CFMachPortSetInvalidationCallBack(configd_port, NULL);
                CFMachPortInvalidate(configd_port);
                CFRelease(configd_port);
                configd_port = NULL;
index 5b7d736a8c2262e4e97743f6590a06848b265171..f3624c60529190e7579af091601da1ab77331c6d 100644 (file)
@@ -8,11 +8,20 @@
                <string>com.apple.certificates</string>
                <string>com.apple.identities</string>
        </array>
+       <key>com.apple.private.mobileinstall.allowedSPI</key>
+       <array>
+               <string>Uninstall</string>
+               <string>Lookup</string>
+       </array>
        <key>com.apple.springboard.launchapplications</key>
        <true/>
        <key>com.apple.multitasking.unlimitedassertions</key>
        <true/>
        <key>com.apple.wifi.manager-access</key>
        <true/>
+       <key>com.apple.coretelephony.Identity.get</key>
+       <true/>
+       <key>com.apple.private.SCNetworkConnection-proxy-user</key>
+       <true/>
 </dict>
 </plist>
index f30790316790479c77629f2eac9a782b3edb977b..87bcbb1035360eb4bba70269d702c09b0e97856c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2004, 2006-2008, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2003, 2004, 2006-2008, 2011, 2012 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -47,7 +47,7 @@
 
 typedef struct {
        CFMutableArrayRef       pInfo;
-       regex_t                 *preg;
+       CFDataRef               pRegex;
 } addContext, *addContextRef;
 
 
@@ -67,39 +67,33 @@ my_CFDictionaryApplyFunction(CFDictionaryRef                        theDict,
 }
 
 
-static void
-identifyKeyForPattern(const void *key, void *val, void *context)
+static Boolean
+keyMatchesPattern(CFStringRef key, CFDataRef pRegex)
 {
-       CFStringRef             storeKey        = (CFStringRef)key;
-       CFDictionaryRef         storeValue      = (CFDictionaryRef)val;
-       CFMutableArrayRef       pInfo           = ((addContextRef)context)->pInfo;
-       regex_t *               preg            = ((addContextRef)context)->preg;
-
        CFIndex                 len;
+       Boolean                 match           = FALSE;
+       regex_t                 *preg;
        int                     reError;
        char                    str_q[256];
        char *                  str             = str_q;
 
-       if (!CFDictionaryContainsKey(storeValue, kSCDData)) {
-               /* if no data (yet) */
-               return;
-       }
-
        /* convert store key to C string */
-       len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(storeKey), kCFStringEncodingASCII) + 1;
+       len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(key), kCFStringEncodingASCII) + 1;
        if (len > (CFIndex)sizeof(str_q))
                str = CFAllocatorAllocate(NULL, len, 0);
-       if (_SC_cfstring_to_cstring(storeKey, str, len, kCFStringEncodingASCII) == NULL) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("identifyKeyForPattern(): could not convert store key to C string"));
+       if (_SC_cfstring_to_cstring(key, str, len, kCFStringEncodingASCII) == NULL) {
+               SCLog(TRUE, LOG_DEBUG, CFSTR("keyMatchesPattern(): could not convert store key to C string"));
                goto done;
        }
 
-       /* compare store key to new notification keys regular expression pattern */
+       /* ALIGN: CF aligns to >8 byte boundries */
+       preg = (regex_t *)(void *)CFDataGetBytePtr(pRegex);
+
+       /* compare key to regular expression pattern */
        reError = regexec(preg, str, 0, NULL, 0);
        switch (reError) {
                case 0 :
-                       /* we've got a match */
-                       CFArrayAppendValue(pInfo, storeKey);
+                       match = TRUE;
                        break;
                case REG_NOMATCH :
                        /* no match */
@@ -108,7 +102,7 @@ identifyKeyForPattern(const void *key, void *val, void *context)
                        char    reErrBuf[256];
 
                        (void)regerror(reError, preg, reErrBuf, sizeof(reErrBuf));
-                       SCLog(TRUE, LOG_DEBUG, CFSTR("identifyKeyForPattern regexec(): %s"), reErrBuf);
+                       SCLog(TRUE, LOG_DEBUG, CFSTR("keyMatchesPattern regexec(): %s"), reErrBuf);
                        break;
                }
        }
@@ -116,12 +110,34 @@ identifyKeyForPattern(const void *key, void *val, void *context)
     done :
 
        if (str != str_q) CFAllocatorDeallocate(NULL, str);
+       return match;
+}
+
+
+static void
+identifyKeyForPattern(const void *key, void *val, void *context)
+{
+       CFStringRef             storeKey        = (CFStringRef)key;
+       CFDictionaryRef         storeValue      = (CFDictionaryRef)val;
+       CFMutableArrayRef       pInfo           = ((addContextRef)context)->pInfo;
+       CFDataRef               pRegex          = ((addContextRef)context)->pRegex;
+
+       if (!CFDictionaryContainsKey(storeValue, kSCDData)) {
+               /* if no data (yet) */
+               return;
+       }
+
+       if (keyMatchesPattern(storeKey, pRegex)) {
+               /* if we've got a match */
+               CFArrayAppendValue(pInfo, storeKey);
+       }
+
        return;
 }
 
 
 static Boolean
-patternCompile(CFStringRef pattern, regex_t *preg, CFStringRef *error)
+patternCompile(CFStringRef pattern, CFDataRef pRegex, CFStringRef *error)
 {
        Boolean         append          = FALSE;
        Boolean         insert          = FALSE;
@@ -174,8 +190,12 @@ patternCompile(CFStringRef pattern, regex_t *preg, CFStringRef *error)
                CFRelease(pattern);
        }
        if (ok) {
+               regex_t *preg;
                int     reError;
 
+               /* ALIGN: CF aligns to >8 byte boundries */
+               preg = (regex_t *)(void *)CFDataGetBytePtr(pRegex);
+
                reError = regcomp(preg, str, REG_EXTENDED);
                if (reError != 0) {
                        char    reErrBuf[256];
@@ -199,13 +219,26 @@ patternCompile(CFStringRef pattern, regex_t *preg, CFStringRef *error)
 }
 
 
+static void
+patternRelease(CFDataRef pRegex)
+{
+       regex_t         *preg;
+
+       /* ALIGN: CF aligns to >8 byte boundries */
+       preg = (regex_t *)(void *)CFDataGetBytePtr(pRegex);
+       regfree(preg);
+
+       return;
+}
+
+
 static CF_RETURNS_RETAINED CFMutableArrayRef
 patternCopy(CFStringRef        pattern)
 {
        CFArrayRef      pInfo;
 
        pInfo = CFDictionaryGetValue(patternData, pattern);
-       return pInfo ? CFArrayCreateMutableCopy(NULL, 0, pInfo) : NULL;
+       return (pInfo != NULL) ? CFArrayCreateMutableCopy(NULL, 0, pInfo) : NULL;
 }
 
 
@@ -224,8 +257,7 @@ patternNew(CFStringRef pattern)
        /* compile the regular expression from the pattern string. */
        pRegex = CFDataCreateMutable(NULL, sizeof(regex_t));
        CFDataSetLength(pRegex, sizeof(regex_t));
-       /* ALIGN: CF aligns to >8 byte boundries */
-       if (!patternCompile(pattern, (regex_t *)(void *)CFDataGetBytePtr(pRegex), &err)) {
+       if (!patternCompile(pattern, pRegex, &err)) {
                CFRelease(err);
                CFRelease(pRegex);
                CFRelease(pInfo);
@@ -241,9 +273,8 @@ patternNew(CFStringRef pattern)
        CFRelease(pSessions);
 
        /* identify/add all existing keys that match the specified pattern */
-       context.pInfo = pInfo;
-       /* ALIGN: CF aligns to >8 byte boundries */
-       context.preg  = (regex_t *)(void *)CFDataGetBytePtr(pRegex);
+       context.pInfo  = pInfo;
+       context.pRegex = pRegex;
        my_CFDictionaryApplyFunction(storeData,
                                     (CFDictionaryApplierFunction)identifyKeyForPattern,
                                     &context);
@@ -277,8 +308,7 @@ patternCopyMatches(CFStringRef pattern)
                CFDataRef       pRegex;
 
                pRegex = CFArrayGetValueAtIndex(pInfo, 0);
-               /* ALIGN: CF aligns to >8 byte boundries */
-               regfree((regex_t *)(void *)CFDataGetBytePtr(pRegex));
+               patternRelease(pRegex);
        }
 
        CFArrayReplaceValues(pInfo, CFRangeMake(0, 2), NULL, 0);
@@ -289,6 +319,52 @@ patternCopyMatches(CFStringRef pattern)
 }
 
 
+__private_extern__
+Boolean
+patternKeyMatches(CFStringRef pattern, CFStringRef key)
+{
+       Boolean                 isNew   = FALSE;
+       Boolean                 match   = FALSE;
+       CFMutableArrayRef       pInfo;
+       CFDataRef               pRegex;
+
+       /* find (or create new instance of) this pattern */
+       pInfo = patternCopy(pattern);
+       if (pInfo != NULL) {
+               CFIndex         n;
+
+               /* if existing pattern, check if known key */
+               n = CFArrayGetCount(pInfo);
+               match = (n > 2) &&
+                       CFArrayContainsValue(pInfo, CFRangeMake(2, n - 2), key);
+               if (match) {
+                       goto done;
+               }
+       } else {
+               /* if new pattern */
+               pInfo = patternNew(pattern);
+               if (pInfo == NULL) {
+                       return FALSE;
+               }
+
+               isNew = TRUE;
+       }
+
+       pRegex = CFArrayGetValueAtIndex(pInfo, 0);
+       match = keyMatchesPattern(key, pRegex);
+
+       if (isNew) {
+               patternRelease(pRegex);
+       }
+
+    done :
+
+       CFRelease(pInfo);
+
+       return match;
+}
+
+
 __private_extern__
 Boolean
 patternAddSession(CFStringRef pattern, CFNumberRef sessionNum)
@@ -344,6 +420,7 @@ patternRemoveSession(CFStringRef pattern, CFNumberRef sessionNum)
 
        /* find instance of this pattern */
        pInfo = patternCopy(pattern);
+       assert(pInfo != NULL);
 
        /* remove this session as a watcher from all matching keys */
        n = CFArrayGetCount(pInfo);
@@ -371,8 +448,7 @@ patternRemoveSession(CFStringRef pattern, CFNumberRef sessionNum)
                /* if no other sessions are watching this pattern */
 
                pRegex = CFArrayGetValueAtIndex(pInfo, 0);
-               /* ALIGN: CF aligns to >8 byte boundries */
-               regfree((regex_t *)(void *)CFDataGetBytePtr(pRegex));
+               patternRelease(pRegex);
                CFDictionaryRemoveValue(patternData, pattern);
        }
 
index 417fedc7e68c6e18ffd1ead7f2fff557b8d88a49..4798b8acc44438507496ba6817240fb484dd6192 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2007 Apple Inc. All rights reserved.
+ * Copyright (c) 2003, 2007, 2012 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -38,6 +38,9 @@ __BEGIN_DECLS
 
 CFArrayRef             patternCopyMatches      (CFStringRef            pattern);
 
+Boolean                        patternKeyMatches       (CFStringRef            pattern,
+                                                CFStringRef            key);
+
 Boolean                        patternAddSession       (CFStringRef            pattern,
                                                 CFNumberRef            sessionNum);
 
index 309631d5bb18b6a81cb3b7950ee9964dac52aad1..90a85ccb5baecc70680feb6344d07b1a309678b8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2009, 2011, 2012 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2009, 2011, 2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -61,19 +61,17 @@ void        _SCDPluginExecInit();
 
 
 #define PLUGIN_ALL(p)          CFSTR(p)
-#if    !TARGET_OS_EMBEDDED
+#if    !TARGET_OS_IPHONE
 #define PLUGIN_MACOSX(p)       CFSTR(p)
 #define PLUGIN_IOS(p)          NULL
-#else  // !TARGET_OS_EMBEDDED
+#else  // !TARGET_OS_IPHONE
 #define PLUGIN_MACOSX(p)       NULL
 #define PLUGIN_IOS(p)          CFSTR(p)
-#endif // !TARGET_OS_EMBEDDED
+#endif // !TARGET_OS_IPHONE
 
 // white-listed (ok-to-load) bundle identifiers
 static const CFStringRef       pluginWhitelist[]       = {
-       PLUGIN_MACOSX("com.apple.SystemConfiguration.Apple80211"),
        PLUGIN_MACOSX("com.apple.SystemConfiguration.ApplicationFirewall"),
-       PLUGIN_MACOSX("com.apple.SystemConfiguration.Bluetooth"),
        PLUGIN_ALL   ("com.apple.SystemConfiguration.EAPOLController"),
        PLUGIN_ALL   ("com.apple.SystemConfiguration.IPConfiguration"),
        PLUGIN_ALL   ("com.apple.SystemConfiguration.IPMonitor"),
@@ -86,7 +84,6 @@ static const CFStringRef      pluginWhitelist[]       = {
 #ifdef HAVE_REACHABILITY_SERVER
        PLUGIN_ALL   ("com.apple.SystemConfiguration.SCNetworkReachability"),
 #endif // HAVE_REACHABILITY_SERVER
-       PLUGIN_MACOSX("com.apple.SystemConfiguration.wwanConfig"),
        PLUGIN_MACOSX("com.apple.print.notification"),
 };
 #define        N_PLUGIN_WHITELIST      (sizeof(pluginWhitelist) / sizeof(pluginWhitelist[0]))
@@ -119,12 +116,14 @@ CFRunLoopRef                      plugin_runLoop          = NULL;
 
 extern SCDynamicStoreBundleLoadFunction                load_IPMonitor;
 extern SCDynamicStoreBundlePrimeFunction       prime_IPMonitor;
+#if    !TARGET_IPHONE_SIMULATOR
 extern SCDynamicStoreBundleLoadFunction                load_InterfaceNamer;
 extern SCDynamicStoreBundleLoadFunction                load_KernelEventMonitor;
 extern SCDynamicStoreBundlePrimeFunction       prime_KernelEventMonitor;
 extern SCDynamicStoreBundleLoadFunction                load_LinkConfiguration;
 extern SCDynamicStoreBundleLoadFunction                load_PreferencesMonitor;
 extern SCDynamicStoreBundlePrimeFunction       prime_PreferencesMonitor;
+#endif // !TARGET_IPHONE_SIMULATOR
 #ifdef HAVE_REACHABILITY_SERVER
 extern SCDynamicStoreBundleLoadFunction                load_SCNetworkReachability;
 #endif // HAVE_REACHABILITY_SERVER
@@ -147,6 +146,7 @@ static const builtin builtin_plugins[] = {
                &prime_IPMonitor,
                NULL
        },
+#if    !TARGET_IPHONE_SIMULATOR
        {
                CFSTR("com.apple.SystemConfiguration.InterfaceNamer"),
                &load_InterfaceNamer,
@@ -175,6 +175,7 @@ static const builtin builtin_plugins[] = {
                &prime_PreferencesMonitor,
                NULL
        },
+#endif // !TARGET_IPHONE_SIMULATOR
 #ifdef HAVE_REACHABILITY_SERVER
        {
                CFSTR("com.apple.SystemConfiguration.SCNetworkReachability"),
@@ -853,15 +854,28 @@ timerCallback(CFRunLoopTimerRef timer, void *info)
 static void
 sortBundles(CFMutableArrayRef orig)
 {
+       CFIndex                 i;
+       CFIndex                 n;
        CFMutableArrayRef       new;
+       CFMutableSetRef         orig_bundleIDs;
+
+       orig_bundleIDs = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
+
+       n = CFArrayGetCount(orig);
+       for (i = 0; i < n; i++) {
+               bundleInfoRef   bundleInfo      = (bundleInfoRef)CFArrayGetValueAtIndex(orig, i);
+               CFStringRef     bundleID        = CFBundleGetIdentifier(bundleInfo->bundle);
+
+               if (bundleID != NULL) {
+                       CFSetAddValue(orig_bundleIDs, bundleID);
+               }
+       }
 
        new = CFArrayCreateMutable(NULL, 0, NULL);
-       while (CFArrayGetCount(orig) > 0) {
-               int     i;
+       while (n > 0) {
                Boolean inserted        = FALSE;
-               int     nOrig           = CFArrayGetCount(orig);
 
-               for (i = 0; i < nOrig; i++) {
+               for (i = 0; i < n; i++) {
                        bundleInfoRef   bundleInfo1     = (bundleInfoRef)CFArrayGetValueAtIndex(orig, i);
                        CFStringRef     bundleID1       = CFBundleGetIdentifier(bundleInfo1->bundle);
                        int             count;
@@ -887,6 +901,12 @@ sortBundles(CFMutableArrayRef orig)
                                int             nNew;
                                CFStringRef     r       = CFArrayGetValueAtIndex(requires, j);
 
+                               if (!CFSetContainsValue(orig_bundleIDs, r)) {
+                                       // if dependency not present
+                                       count--;
+                                       continue;
+                               }
+
                                nNew = CFArrayGetCount(new);
                                for (k = 0; k < nNew; k++) {
                                        bundleInfoRef   bundleInfo2     = (bundleInfoRef)CFArrayGetValueAtIndex(new, k);
@@ -910,6 +930,8 @@ sortBundles(CFMutableArrayRef orig)
                        SCLog(TRUE, LOG_NOTICE, CFSTR("Bundles have circular dependency!!!"));
                        break;
                }
+
+               n = CFArrayGetCount(orig);
        }
        if (CFArrayGetCount(orig) > 0) {
                /* we have a circular dependency, append remaining items on new array */
@@ -922,6 +944,7 @@ sortBundles(CFMutableArrayRef orig)
        CFArrayRemoveAllValues(orig);
        CFArrayAppendArray(orig, new, CFRangeMake(0, CFArrayGetCount(new)));
        CFRelease(new);
+       CFRelease(orig_bundleIDs);
        return;
 }
 
@@ -972,9 +995,24 @@ plugin_exec(void *arg)
                        CFArrayRef      bundles;
                        CFURLRef        url;
 
+#if    TARGET_IPHONE_SIMULATOR
+                       const char      *path_sim_prefix;
+
+                       path_sim_prefix = getenv("IPHONE_SIMULATOR_ROOT");
+                       if ((path_sim_prefix != NULL) && (strcmp(path_sim_prefix, ".") != 0)) {
+                               char    path_sim[MAXPATHLEN];
+
+                               strlcpy(path_sim, path_sim_prefix, sizeof(path_sim));
+                               strlcat(path_sim, path, sizeof(path_sim));
+                               strlcpy(path, path_sim, sizeof(path));
+                       } else {
+                               path[0] = '\0';
+                       }
+#endif // TARGET_IPHONE_SIMULATOR
+
                        /* load any available bundle */
                        strlcat(path, BUNDLE_DIRECTORY, sizeof(path));
-                       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("searching for bundles in \".\""));
+                       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("searching for bundles in \"%s\""), path);
                        url = CFURLCreateFromFileSystemRepresentation(NULL,
                                                                      (UInt8 *)path,
                                                                      strlen(path),
@@ -1048,12 +1086,12 @@ plugin_exec(void *arg)
         * Since xpcd calls getpwuid_r() during its initialization, it will
         * block until the platform UUID is available.
         */
-       for (int i = 0; i < CFArrayGetCount(allBundles); i++) {
+       for (i = 0; i < CFArrayGetCount(allBundles); i++) {
                bundleInfoRef   bi              = (bundleInfoRef)CFArrayGetValueAtIndex(allBundles, i);
                CFStringRef     bundleID        = CFBundleGetIdentifier(bi->bundle);
 
                if (_SC_CFEqual(bundleID,
-                               CFSTR("com.apple.SystemConfiguration.InterfaceNamer")))
+                               CFSTR("com.apple.SystemConfiguration.InterfaceNamer")))
                {
                        CFArrayRemoveValueAtIndex(allBundles, i);
                        CFArrayInsertValueAtIndex(allBundles, 0, bi);
index cbb5b961c77a2df59e162b03a9934df8fbbff7e1..f6c88216bf9ad2f828e7eb61cb98f48598c37427 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2001, 2003-2005, 2007-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2003-2005, 2007-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * - initial revision
  */
 
+#include <SystemConfiguration/SystemConfiguration.h>
 #include "configd.h"
 #include "configd_server.h"
+#include "pattern.h"
 #include "session.h"
 
 #include <unistd.h>
@@ -52,20 +54,6 @@ static CFRunLoopRef  sessionRunLoop  = NULL;
 static serverSessionRef        temp_session    = NULL;
 
 
-static void
-CFMachPortInvalidateSessionCallback(CFMachPortRef port, void *info)
-{
-       CFRunLoopRef    currentRunLoop  = CFRunLoopGetCurrent();
-
-       // Bear trap
-       if (!_SC_CFEqual(currentRunLoop, sessionRunLoop)) {
-               _SC_crash("SCDynamicStore CFMachPort invalidation error",
-                          CFSTR("CFMachPort invalidated"),
-                          CFSTR("An SCDynamicStore CFMachPort has incorrectly been invalidated."));
-       }
-}
-
-
 __private_extern__
 serverSessionRef
 getSession(mach_port_t server)
@@ -120,11 +108,17 @@ tempSession(mach_port_t server, CFStringRef name, audit_token_t auditToken)
                (void) __SCDynamicStoreOpen(&temp_session->store, NULL);
        });
 
-       /* save audit token */
-       temp_session->auditToken        = auditToken;
-       temp_session->callerEUID        = -1;           /* not "root" */
-       temp_session->callerRootAccess  = UNKNOWN;
-       temp_session->callerWriteAccess = UNKNOWN;
+       /* save audit token, caller entitlements */
+       temp_session->auditToken                = auditToken;
+       temp_session->callerEUID                = 1;            /* not "root" */
+       temp_session->callerRootAccess          = UNKNOWN;
+#if    TARGET_OS_IPHONE || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080/*FIXME*/)
+       if ((temp_session->callerWriteEntitlement != NULL) &&
+           (temp_session->callerWriteEntitlement != kCFNull)) {
+               CFRelease(temp_session->callerWriteEntitlement);
+       }
+       temp_session->callerWriteEntitlement    = kCFNull;      /* UNKNOWN */
+#endif  // TARGET_OS_IPHONE || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080/*FIXME*/)
 
        /* save name */
        storePrivate = (SCDynamicStorePrivateRef)temp_session->store;
@@ -221,13 +215,6 @@ addSession(mach_port_t server, CFStringRef (*copyDescription)(const void *info))
                                                               configdCallback,
                                                               &context);
 
-       //
-       // Set bear trap (an invalidation callback) to catch other
-       // threads stomping on us
-       //
-       CFMachPortSetInvalidationCallBack(sessions[n]->serverPort,
-                                         CFMachPortInvalidateSessionCallback);
-
        if (n > 0) {
                // insert send right that will be moved to the client
                (void) mach_port_insert_right(mach_task_self(),
@@ -236,12 +223,14 @@ addSession(mach_port_t server, CFStringRef (*copyDescription)(const void *info))
                                              MACH_MSG_TYPE_MAKE_SEND);
        }
 
-       sessions[n]->key                 = mp;
-//     sessions[n]->serverRunLoopSource = NULL;
-//     sessions[n]->store               = NULL;
-       sessions[n]->callerEUID          = 1;           /* not "root" */
-       sessions[n]->callerRootAccess    = UNKNOWN;
-       sessions[n]->callerWriteAccess   = UNKNOWN;
+       sessions[n]->key                        = mp;
+//     sessions[n]->serverRunLoopSource        = NULL;
+//     sessions[n]->store                      = NULL;
+       sessions[n]->callerEUID                 = 1;            /* not "root" */
+       sessions[n]->callerRootAccess           = UNKNOWN;
+#if    TARGET_OS_IPHONE || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080/*FIXME*/)
+       sessions[n]->callerWriteEntitlement     = kCFNull;      /* UNKNOWN */
+#endif  // TARGET_OS_IPHONE || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080/*FIXME*/)
 
        return sessions[n];
 }
@@ -284,6 +273,16 @@ cleanupSession(mach_port_t server)
                         */
                        (void) mach_port_mod_refs(mach_task_self(), server, MACH_PORT_RIGHT_RECEIVE, -1);
 
+#if    TARGET_OS_IPHONE || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080/*FIXME*/)
+                       /*
+                        * release any entitlement info
+                        */
+                       if ((thisSession->callerWriteEntitlement != NULL) &&
+                           (thisSession->callerWriteEntitlement != kCFNull)) {
+                               CFRelease(thisSession->callerWriteEntitlement);
+                       }
+#endif  // TARGET_OS_IPHONE || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080/*FIXME*/)
+
                        /*
                         * We don't need any remaining information in the
                         * sessionData dictionary, remove it.
@@ -374,7 +373,7 @@ listSessions(FILE *f)
 }
 
 
-#if    TARGET_OS_IPHONE || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)
+#if    TARGET_OS_IPHONE || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080/*FIXME*/)
 
 #include <Security/Security.h>
 #include <Security/SecTask.h>
@@ -397,66 +396,81 @@ sessionName(serverSessionRef session)
        return (name != NULL) ? name : CFSTR("???");
 }
 
-
-static Boolean
-hasEntitlement(serverSessionRef session, CFStringRef entitlement)
+static CFTypeRef
+copyEntitlement(serverSessionRef session, CFStringRef entitlement)
 {
-       Boolean         hasEntitlement  = FALSE;
        SecTaskRef      task;
+       CFTypeRef       value   = NULL;
 
-       /* Create the security task from the audit token. */
+       // Create the security task from the audit token
        task = SecTaskCreateWithAuditToken(NULL, session->auditToken);
        if (task != NULL) {
                CFErrorRef      error   = NULL;
-               CFTypeRef       value;
 
-               /* Get the value for the entitlement. */
+               // Get the value for the entitlement
                value = SecTaskCopyValueForEntitlement(task, entitlement, &error);
-               if (value != NULL) {
-                       if (isA_CFBoolean(value)) {
-                               if (CFBooleanGetValue(value)) {
-                                       /* if client DOES have entitlement */
-                                       hasEntitlement = TRUE;
-                               }
-                       } else {
+               if ((value == NULL) && (error != NULL)) {
+                       CFIndex         code    = CFErrorGetCode(error);
+                       CFStringRef     domain  = CFErrorGetDomain(error);
+
+                       if (!CFEqual(domain, kCFErrorDomainMach) ||
+                           ((code != kIOReturnInvalid) && (code != kIOReturnNotFound))) {
+                               // if unexpected error
                                SCLog(TRUE, LOG_ERR,
-                                     CFSTR("hasEntitlement: entitlement not valid: %@"),
+                                     CFSTR("SecTaskCopyValueForEntitlement(,\"%@\",) failed, error = %@ : %@"),
+                                     entitlement,
+                                     error,
                                      sessionName(session));
                        }
-
-                       CFRelease(value);
-               }
-               if (error != NULL) {
-                       SCLog(TRUE,
-                             (value == NULL) ? LOG_ERR : LOG_DEBUG,
-                             CFSTR("hasEntitlement SecTaskCopyValueForEntitlement() %s, error domain=%@, error code=%lx"),
-                             (value == NULL) ? "failed" : "warned",
-                             CFErrorGetDomain(error),
-                             CFErrorGetCode(error));
                        CFRelease(error);
                }
 
                CFRelease(task);
        } else {
                SCLog(TRUE, LOG_ERR,
-                     CFSTR("hasEntitlement SecTaskCreateWithAuditToken() failed: %@"),
+                     CFSTR("SecTaskCreateWithAuditToken() failed: %@"),
                      sessionName(session));
        }
 
-       return hasEntitlement;
+       return value;
 }
 
-#endif  // TARGET_OS_IPHONE || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)
+#endif  // TARGET_OS_IPHONE || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080/*FIXME*/)
+
+
+static pid_t
+sessionPid(serverSessionRef session)
+{
+       pid_t   caller_pid;
+
+#if     (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) && !TARGET_OS_IPHONE
+       caller_pid = audit_token_to_pid(session->auditToken);
+#else  // (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) && !TARGET_OS_IPHONE
+       audit_token_to_au32(session->auditToken,
+                           NULL,               // auidp
+                           NULL,               // euid
+                           NULL,               // egid
+                           NULL,               // ruid
+                           NULL,               // rgid
+                           &caller_pid,        // pid
+                           NULL,               // asid
+                           NULL);              // tid
+#endif // (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) && !TARGET_OS_IPHONE
+
+       return caller_pid;
+}
 
 
 __private_extern__
 Boolean
 hasRootAccess(serverSessionRef session)
 {
+#if    !TARGET_IPHONE_SIMULATOR
+
        if (session->callerRootAccess == UNKNOWN) {
-               /*
-                * get the credentials associated with the caller.
-                */
+#if     (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) && !TARGET_OS_IPHONE
+               session->callerEUID = audit_token_to_euid(session->auditToken);
+#else  // (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) && !TARGET_OS_IPHONE
                audit_token_to_au32(session->auditToken,
                                    NULL,                       // auidp
                                    &session->callerEUID,       // euid
@@ -466,35 +480,127 @@ hasRootAccess(serverSessionRef session)
                                    NULL,                       // pid
                                    NULL,                       // asid
                                    NULL);                      // tid
-
+#endif // (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) && !TARGET_OS_IPHONE
                session->callerRootAccess = (session->callerEUID == 0) ? YES : NO;
        }
 
        return (session->callerRootAccess == YES) ? TRUE : FALSE;
+
+#else  // !TARGET_IPHONE_SIMULATOR
+
+       /*
+        * assume that all processes interacting with
+        * the iOS Simulator "configd" are OK.
+        */
+       return TRUE;
+
+#endif // !TARGET_IPHONE_SIMULATOR
 }
 
 
 __private_extern__
 Boolean
-hasWriteAccess(serverSessionRef session)
+hasWriteAccess(serverSessionRef session, CFStringRef key)
 {
-       if (session->callerWriteAccess == UNKNOWN) {
-               /* assume that the client DOES NOT have the entitlement */
-               session->callerWriteAccess = NO;
+       Boolean isSetup;
 
-               if (hasRootAccess(session)) {
-                       // grant write access to eUID==0 processes
-                       session->callerWriteAccess = YES;
+       // need to special case writing "Setup:" keys
+       isSetup = CFStringHasPrefix(key, kSCDynamicStoreDomainSetup);
+
+       if (hasRootAccess(session)) {
+               pid_t   pid;
+
+               // grant write access to eUID==0 processes
+
+               pid = sessionPid(session);
+               if (isSetup && (pid != getpid())) {
+                       /*
+                        * WAIT!!!
+                        *
+                        * This is NOT configd (or a plugin) trying to
+                        * write to an SCDynamicStore "Setup:" key.  In
+                        * general, this is unwise and we should at the
+                        * very least complain.
+                        */
+                       SCLog(TRUE, LOG_ERR,
+                             CFSTR("*** Non-configd process (pid=%d) attempting to modify \"%@\" ***"),
+                             pid,
+                             key);
                }
-#if    TARGET_OS_IPHONE || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)
-               else if (hasEntitlement(session, kSCWriteEntitlementName)) {
-                       // grant write access to "entitled" processes
-                       session->callerWriteAccess = YES;
+
+               return TRUE;
+       }
+
+       if (isSetup) {
+               /*
+                * STOP!!!
+                *
+                * This is a non-root process trying to write to
+                * an SCDynamicStore "Setup:" key.  This is not
+                * something we should ever allow (regardless of
+                * any entitlements).
+                */
+               SCLog(TRUE, LOG_ERR,
+                     CFSTR("*** Non-root process (pid=%d) attempting to modify \"%@\" ***"),
+                     sessionPid(session),
+                     key);
+
+               //return FALSE;         // return FALSE when rdar://9811832 has beed fixed
+       }
+
+#if    TARGET_OS_IPHONE || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080/*FIXME*/)
+       if (session->callerWriteEntitlement == kCFNull) {
+               session->callerWriteEntitlement = copyEntitlement(session,
+                                                                 kSCWriteEntitlementName);
+       }
+
+       if (session->callerWriteEntitlement == NULL) {
+               return FALSE;
+       }
+
+       if (isA_CFBoolean(session->callerWriteEntitlement) &&
+           CFBooleanGetValue(session->callerWriteEntitlement)) {
+               // grant write access to "entitled" processes
+               return TRUE;
+       }
+
+       if (isA_CFDictionary(session->callerWriteEntitlement)) {
+               CFArrayRef      keys;
+               CFArrayRef      patterns;
+
+               keys = CFDictionaryGetValue(session->callerWriteEntitlement, CFSTR("keys"));
+               if (isA_CFArray(keys)) {
+                       if (CFArrayContainsValue(keys,
+                                                CFRangeMake(0, CFArrayGetCount(keys)),
+                                                key)) {
+                               // if key matches one of the entitlement "keys", grant
+                               // write access
+                               return TRUE;
+                       }
+               }
+
+               patterns = CFDictionaryGetValue(session->callerWriteEntitlement, CFSTR("patterns"));
+               if (isA_CFArray(patterns)) {
+                       CFIndex         i;
+                       CFIndex         n       = CFArrayGetCount(patterns);
+
+                       for (i = 0; i < n; i++) {
+                               CFStringRef     pattern;
+
+                               pattern = CFArrayGetValueAtIndex(patterns, i);
+                               if (isA_CFString(pattern)) {
+                                       if (patternKeyMatches(pattern, key)) {
+                                               // if key matches one of the entitlement
+                                               // "patterns", grant write access
+                                               return TRUE;
+                                       }
+                               }
+                       }
                }
-#endif  // TARGET_OS_IPHONE || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)
        }
+#endif  // TARGET_OS_IPHONE || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080/*FIXME*/)
 
-       return (session->callerWriteAccess == YES) ? TRUE : FALSE;
+       return FALSE;
 }
 
 
@@ -510,6 +616,9 @@ hasPathAccess(serverSessionRef session, const char *path)
                return FALSE;
        }
 
+#if    (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) && !TARGET_OS_IPHONE
+       pid = audit_token_to_pid(session->auditToken);
+#else  // (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) && !TARGET_OS_IPHONE
        audit_token_to_au32(session->auditToken,
                            NULL,               // auidp
                            NULL,               // euid
@@ -519,8 +628,11 @@ hasPathAccess(serverSessionRef session, const char *path)
                            &pid,               // pid
                            NULL,               // asid
                            NULL);              // tid
-
-       if (sandbox_check(pid, "file-write-data", SANDBOX_FILTER_PATH, realPath) > 0) {
+#endif // (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) && !TARGET_OS_IPHONE
+       if (sandbox_check(pid,                                                  // pid
+                         "file-write-data",                                    // operation
+                         SANDBOX_FILTER_PATH | SANDBOX_CHECK_NO_REPORT,        // sandbox_filter_type
+                         realPath) > 0) {                                      // ...
                SCLog(TRUE, LOG_DEBUG, CFSTR("hasPathAccess sandbox access denied: %s"), strerror(errno));
                return FALSE;
        }
index 68d8f910ad322887126cff19259454f95a8d4dfd..ab4c4d62786e491e64164e35be3a55e756b2f5af 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2001, 2005-2007, 2009-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2005-2007, 2009-2012 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 
 
 #if    TARGET_OS_IPHONE || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)
+/*
+ * SCDynamicStore write access entitlement
+ *
+ *   Key   : "com.apple.SystemConfiguration.SCDynamicStore-write-access"
+ *   Value : Boolean
+ *             TRUE == allow SCDynamicStore write access for this process
+ *
+ *           Dictionary
+ *             Key   : "keys"
+ *             Value : <array> of CFString with write access allowed for
+ *                     each SCDynamicStore key matching the string(s)
+ *
+ *             Key   : "patterns"
+ *             Value : <array> of CFString with write access allowed for
+ *                     each SCDynamicStore key matching the regex pattern(s)
+ */
 #define        kSCWriteEntitlementName CFSTR("com.apple.SystemConfiguration.SCDynamicStore-write-access")
 #endif  // TARGET_OS_IPHONE || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)
 
@@ -69,8 +85,18 @@ typedef struct {
        /* root access credential associated with this "open" session */
        lazyBoolean             callerRootAccess;
 
-       /* write access entitlement associated with this "open" session */
-       lazyBoolean             callerWriteAccess;
+#if    TARGET_OS_IPHONE || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080/*FIXME*/)
+       /*
+        * write access entitlement associated with this "open" session
+        *
+        *   kCFNull            caller entitlements unknown (need to fetch)
+        *   NULL               no entitlement
+        *   CFBoolean          true/false
+        *   CFDictionary       "keys"     = CFArray[writable keys]
+        *                      "patterns" = CFArray[writable patterns]
+        */
+       CFTypeRef               callerWriteEntitlement;
+#endif  // TARGET_OS_IPHONE || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080/*FIXME*/)
 
 } serverSession, *serverSessionRef;
 
@@ -91,7 +117,8 @@ void                 listSessions    (FILE           *f);
 
 Boolean                        hasRootAccess   (serverSessionRef       session);
 
-Boolean                        hasWriteAccess  (serverSessionRef       session);
+Boolean                        hasWriteAccess  (serverSessionRef       session,
+                                        CFStringRef            key);
 
 Boolean                        hasPathAccess   (serverSessionRef       session,
                                         const char             *path);
index ebce9e4d5fefa75cf28bcd48047ddafcdfd94b9b..2fced37ca811fa11fedce78b55e9e474f33524a2 100644 (file)
                        );
                        dependencies = (
                                15A5A2710D5B942D0087BDA0 /* PBXTargetDependency */,
+                               15E1B06416EBAF2A00E5F06F /* PBXTargetDependency */,
+                               15E1B06616EBAF2A00E5F06F /* PBXTargetDependency */,
+                               15AB752216EC005A00FAA8CE /* PBXTargetDependency */,
+                               15AB752416EC005A00FAA8CE /* PBXTargetDependency */,
+                               15D3083016F3EAD000014F82 /* PBXTargetDependency */,
+                               15D3083216F3EAD000014F82 /* PBXTargetDependency */,
+                               15E1B03E16EBAB8A00E5F06F /* PBXTargetDependency */,
+                               15E1B04016EBAB9400E5F06F /* PBXTargetDependency */,
                        );
                        name = "configd_base-EmbeddedSimulator";
                        productName = Frameworks;
                        name = configd_base;
                        productName = Frameworks;
                };
+               157FDE3B164A075F0040D6A8 /* configd_libSystem-EmbeddedSimulator */ = {
+                       isa = PBXAggregateTarget;
+                       buildConfigurationList = 157FDE3E164A075F0040D6A8 /* Build configuration list for PBXAggregateTarget "configd_libSystem-EmbeddedSimulator" */;
+                       buildPhases = (
+                       );
+                       dependencies = (
+                               15732AE616EA6BCE00F3AC4C /* PBXTargetDependency */,
+                       );
+                       name = "configd_libSystem-EmbeddedSimulator";
+                       productName = configd_libSystem;
+               };
                158316CF0CFB774B006F62B9 /* configd_base-Embedded */ = {
                        isa = PBXAggregateTarget;
                        buildConfigurationList = 158316D80CFB774B006F62B9 /* Build configuration list for PBXAggregateTarget "configd_base-Embedded" */;
                        name = "configd_executables-Embedded";
                        productName = configd_executables;
                };
-               1583E9E01083959E00A3BC0C /* All-EmbeddedOther */ = {
-                       isa = PBXAggregateTarget;
-                       buildConfigurationList = 1583E9E91083959E00A3BC0C /* Build configuration list for PBXAggregateTarget "All-EmbeddedOther" */;
-                       buildPhases = (
-                       );
-                       dependencies = (
-                               15AC515810839608004A9ED5 /* PBXTargetDependency */,
-                               15AC515B1083960E004A9ED5 /* PBXTargetDependency */,
-                               15AC515D10839613004A9ED5 /* PBXTargetDependency */,
-                               15AC515F1083961E004A9ED5 /* PBXTargetDependency */,
-                       );
-                       name = "All-EmbeddedOther";
-                       productName = Embedded;
-               };
-               1583E9FD108395BB00A3BC0C /* configd_libSystem-EmbeddedOther */ = {
-                       isa = PBXAggregateTarget;
-                       buildConfigurationList = 1583EA01108395BB00A3BC0C /* Build configuration list for PBXAggregateTarget "configd_libSystem-EmbeddedOther" */;
-                       buildPhases = (
-                       );
-                       dependencies = (
-                               15AC516110839649004A9ED5 /* PBXTargetDependency */,
-                       );
-                       name = "configd_libSystem-EmbeddedOther";
-                       productName = configd_libSystem;
-               };
-               1583EA11108395BB00A3BC0C /* configd_base-EmbeddedOther */ = {
-                       isa = PBXAggregateTarget;
-                       buildConfigurationList = 1583EA16108395BB00A3BC0C /* Build configuration list for PBXAggregateTarget "configd_base-EmbeddedOther" */;
-                       buildPhases = (
-                       );
-                       dependencies = (
-                               15AC516310839666004A9ED5 /* PBXTargetDependency */,
-                               15AC51651083966B004A9ED5 /* PBXTargetDependency */,
-                       );
-                       name = "configd_base-EmbeddedOther";
-                       productName = Frameworks;
-               };
-               1583EAAC108395BB00A3BC0C /* configd_plugins-EmbeddedOther */ = {
-                       isa = PBXAggregateTarget;
-                       buildConfigurationList = 1583EAC7108395BB00A3BC0C /* Build configuration list for PBXAggregateTarget "configd_plugins-EmbeddedOther" */;
-                       buildPhases = (
-                       );
-                       dependencies = (
-                               15AC5185108396D2004A9ED5 /* PBXTargetDependency */,
-                               15AC5183108396D2004A9ED5 /* PBXTargetDependency */,
-                               15AC5189108396D2004A9ED5 /* PBXTargetDependency */,
-                               15AC5187108396D2004A9ED5 /* PBXTargetDependency */,
-                               15AC5181108396D2004A9ED5 /* PBXTargetDependency */,
-                               15AC517F108396D2004A9ED5 /* PBXTargetDependency */,
-                               15AC517D108396D2004A9ED5 /* PBXTargetDependency */,
-                               15AC517B108396D2004A9ED5 /* PBXTargetDependency */,
-                               15AC5179108396D2004A9ED5 /* PBXTargetDependency */,
-                               15AC5173108396D2004A9ED5 /* PBXTargetDependency */,
-                               15AC5171108396D2004A9ED5 /* PBXTargetDependency */,
-                               1528C0131357420300691881 /* PBXTargetDependency */,
-                               1528C0151357420300691881 /* PBXTargetDependency */,
-                       );
-                       name = "configd_plugins-EmbeddedOther";
-                       productName = Plugins;
-               };
-               1583EB41108395BD00A3BC0C /* configd_executables-EmbeddedOther */ = {
-                       isa = PBXAggregateTarget;
-                       buildConfigurationList = 1583EB48108395BD00A3BC0C /* Build configuration list for PBXAggregateTarget "configd_executables-EmbeddedOther" */;
-                       buildPhases = (
-                       );
-                       dependencies = (
-                               15AC516E108396B7004A9ED5 /* PBXTargetDependency */,
-                               15AC516C108396B7004A9ED5 /* PBXTargetDependency */,
-                               15AC516A108396B7004A9ED5 /* PBXTargetDependency */,
-                       );
-                       name = "configd_executables-EmbeddedOther";
-                       productName = configd_executables;
-               };
                159D542007528E7C004F8947 /* configd_plugins */ = {
                        isa = PBXAggregateTarget;
                        buildConfigurationList = 156EB61E0905594A00EEF749 /* Build configuration list for PBXAggregateTarget "configd_plugins" */;
                        name = All;
                        productName = "configd (Aggregate)";
                };
+               15E83104167F9AF600FD51EC /* EVERYTHING */ = {
+                       isa = PBXAggregateTarget;
+                       buildConfigurationList = 15E83107167F9AF600FD51EC /* Build configuration list for PBXAggregateTarget "EVERYTHING" */;
+                       buildPhases = (
+                       );
+                       dependencies = (
+                               15E83109167F9B0600FD51EC /* PBXTargetDependency */,
+                               15E8310B167F9B0C00FD51EC /* PBXTargetDependency */,
+                               15E8310D167F9B1200FD51EC /* PBXTargetDependency */,
+                       );
+                       name = EVERYTHING;
+                       productName = EVERYTHING;
+               };
                15FD13BF0D59485000F9409C /* All-EmbeddedSimulator */ = {
                        isa = PBXAggregateTarget;
                        buildConfigurationList = 15FD13C60D59485000F9409C /* Build configuration list for PBXAggregateTarget "All-EmbeddedSimulator" */;
                        buildPhases = (
                        );
                        dependencies = (
+                               157FDE44164A079B0040D6A8 /* PBXTargetDependency */,
                                151FE37A0D5B713C000D6DB1 /* PBXTargetDependency */,
                        );
                        name = "All-EmbeddedSimulator";
 /* Begin PBXBuildFile section */
                15060818075A00A300B147BA /* SCSchemaDefinitions.c in Sources */ = {isa = PBXBuildFile; fileRef = 150607BD075A00A200B147BA /* SCSchemaDefinitions.c */; };
                1506081A075A00A300B147BA /* SCSchemaDefinitions.h in Headers */ = {isa = PBXBuildFile; fileRef = 150607DE075A00A300B147BA /* SCSchemaDefinitions.h */; settings = {ATTRIBUTES = (Public, ); }; };
+               150BEC1814CA24F900237116 /* dnsinfo_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B73F0D05FD1B670096477F /* dnsinfo_server.c */; };
+               150BEC1A14CA252200237116 /* dnsinfo_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B73F0D05FD1B670096477F /* dnsinfo_server.c */; };
                150D7E1E0D16DC6C00AF4BED /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1520A3DE0846B2DC0010B584 /* Security.framework */; };
-               151E0CA31378EE1000C5DA2A /* network_information.h in Headers */ = {isa = PBXBuildFile; fileRef = D6986A781368913C0091C931 /* network_information.h */; settings = {ATTRIBUTES = (Public, ); }; };
-               151E0CA51378EE3B00C5DA2A /* network_information.c in Sources */ = {isa = PBXBuildFile; fileRef = D6986A77136891300091C931 /* network_information.c */; };
                1520A3870846829A0010B584 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15CB6A6F05C0722B0099E85F /* CoreFoundation.framework */; };
                1520A3DF0846B2DD0010B584 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1520A3DE0846B2DC0010B584 /* Security.framework */; };
                152140020E93EC6500DACD2C /* logger.c in Sources */ = {isa = PBXBuildFile; fileRef = 1531D3DB0E93E6DA00248432 /* logger.c */; };
                1522FCFB0FA7FE4B00B24128 /* dnsinfo_flatfile.c in Sources */ = {isa = PBXBuildFile; fileRef = 1522FCE50FA7FD7000B24128 /* dnsinfo_flatfile.c */; };
                152691DB1129EEA6006BD2D5 /* BridgeConfiguration.c in Sources */ = {isa = PBXBuildFile; fileRef = 15FD7B3B101E439200C56621 /* BridgeConfiguration.c */; };
                152691DC1129EEAD006BD2D5 /* BridgeConfiguration.c in Sources */ = {isa = PBXBuildFile; fileRef = 15FD7B3B101E439200C56621 /* BridgeConfiguration.c */; };
-               152691DD1129EEB1006BD2D5 /* BridgeConfiguration.c in Sources */ = {isa = PBXBuildFile; fileRef = 15FD7B3B101E439200C56621 /* BridgeConfiguration.c */; };
                152691DE1129EEC2006BD2D5 /* VLANConfiguration.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69B605C0722B0099E85F /* VLANConfiguration.c */; };
                152691DF1129EEC8006BD2D5 /* VLANConfiguration.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69B605C0722B0099E85F /* VLANConfiguration.c */; };
-               152691E01129EECB006BD2D5 /* VLANConfiguration.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69B605C0722B0099E85F /* VLANConfiguration.c */; };
                1528BFEF135733F500691881 /* SCNetworkReachabilityServer_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 15C330BB134B92780028E36B /* SCNetworkReachabilityServer_server.c */; };
                1528BFF313573FEE00691881 /* SCNetworkReachabilityServer_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 15C330BB134B92780028E36B /* SCNetworkReachabilityServer_server.c */; };
-               1528C0021357401900691881 /* SCNetworkReachabilityServer_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 15C330BB134B92780028E36B /* SCNetworkReachabilityServer_server.c */; };
                1528C0171357465900691881 /* libSCNetworkReachability.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1528BFF713573FEE00691881 /* libSCNetworkReachability.a */; };
                1528C019135746BB00691881 /* libSCNetworkReachability.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1528BFE21357305400691881 /* libSCNetworkReachability.a */; };
-               1528C01A135746D700691881 /* libSCNetworkReachability.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1528C0061357401900691881 /* libSCNetworkReachability.a */; };
                152E0E7F10FE820E00E402F2 /* helper.defs in Sources */ = {isa = PBXBuildFile; fileRef = 152E0E7E10FE820E00E402F2 /* helper.defs */; settings = {ATTRIBUTES = (Server, ); }; };
                152E0E8010FE820E00E402F2 /* helper.defs in Sources */ = {isa = PBXBuildFile; fileRef = 152E0E7E10FE820E00E402F2 /* helper.defs */; settings = {ATTRIBUTES = (Server, ); }; };
-               152E0E8110FE820E00E402F2 /* helper.defs in Sources */ = {isa = PBXBuildFile; fileRef = 152E0E7E10FE820E00E402F2 /* helper.defs */; settings = {ATTRIBUTES = (Server, ); }; };
                152E0E8910FE824000E402F2 /* helper_types.h in Headers */ = {isa = PBXBuildFile; fileRef = 152E0E8810FE824000E402F2 /* helper_types.h */; };
                152E0E8A10FE824000E402F2 /* helper_types.h in Headers */ = {isa = PBXBuildFile; fileRef = 152E0E8810FE824000E402F2 /* helper_types.h */; };
-               152E0E8B10FE824000E402F2 /* helper_types.h in Headers */ = {isa = PBXBuildFile; fileRef = 152E0E8810FE824000E402F2 /* helper_types.h */; };
                152E68C10A2C89C70011FDA8 /* SCPreferencesKeychainPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 152E68C00A2C89C70011FDA8 /* SCPreferencesKeychainPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
                152E68C30A2C89E30011FDA8 /* SCPreferencesKeychainPrivate.c in Sources */ = {isa = PBXBuildFile; fileRef = 152E68C20A2C89E30011FDA8 /* SCPreferencesKeychainPrivate.c */; };
+               153338BC14BE7978004FCE22 /* libSystemConfiguration_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 153338BA14BE7978004FCE22 /* libSystemConfiguration_client.c */; };
+               153338BD14BE7978004FCE22 /* libSystemConfiguration_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 153338BA14BE7978004FCE22 /* libSystemConfiguration_client.c */; };
+               153338BF14BE7978004FCE22 /* libSystemConfiguration_client.h in Headers */ = {isa = PBXBuildFile; fileRef = 153338BB14BE7978004FCE22 /* libSystemConfiguration_client.h */; };
+               153338C014BE7978004FCE22 /* libSystemConfiguration_client.h in Headers */ = {isa = PBXBuildFile; fileRef = 153338BB14BE7978004FCE22 /* libSystemConfiguration_client.h */; };
+               153ACCA814E322D5005029A5 /* network_information_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 153ACCA614E322D5005029A5 /* network_information_server.c */; };
+               153ACCA914E322D5005029A5 /* network_information_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 153ACCA614E322D5005029A5 /* network_information_server.c */; };
+               153ACCAB14E322D5005029A5 /* network_information_server.h in Headers */ = {isa = PBXBuildFile; fileRef = 153ACCA714E322D5005029A5 /* network_information_server.h */; };
+               153ACCAC14E322D5005029A5 /* network_information_server.h in Headers */ = {isa = PBXBuildFile; fileRef = 153ACCA714E322D5005029A5 /* network_information_server.h */; };
                1540E3610987DA9500157C07 /* com.apple.configd.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1540E3600987DA9500157C07 /* com.apple.configd.plist */; };
                154361E00752C81800A8EC6C /* set-hostname.c in Sources */ = {isa = PBXBuildFile; fileRef = 159D53AB07528B36004F8947 /* set-hostname.c */; };
                1543636B0752D03C00A8EC6C /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1543636A0752D03C00A8EC6C /* IOKit.framework */; };
                156CA47F0EF853BB00C59A18 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1543636A0752D03C00A8EC6C /* IOKit.framework */; };
                1572C4A90CFB55B400E2776E /* SCSchemaDefinitions.h in Headers */ = {isa = PBXBuildFile; fileRef = 150607DE075A00A300B147BA /* SCSchemaDefinitions.h */; settings = {ATTRIBUTES = (Public, ); }; };
                1572C4AA0CFB55B400E2776E /* SystemConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB691305C0722B0099E85F /* SystemConfiguration.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
-               1572C4AB0CFB55B400E2776E /* SCPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB691505C0722B0099E85F /* SCPrivate.h */; settings = {ATTRIBUTES = (Project, Private, ); }; };
+               1572C4AB0CFB55B400E2776E /* SCPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB691505C0722B0099E85F /* SCPrivate.h */; settings = {ATTRIBUTES = (Private, Project, ); }; };
                1572C4AC0CFB55B400E2776E /* SCDPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB691705C0722B0099E85F /* SCDPlugin.h */; settings = {ATTRIBUTES = (Private, ); }; };
                1572C4AD0CFB55B400E2776E /* SCDynamicStoreInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB691B05C0722B0099E85F /* SCDynamicStoreInternal.h */; settings = {ATTRIBUTES = (Project, ); }; };
                1572C4AE0CFB55B400E2776E /* SCDynamicStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB691D05C0722B0099E85F /* SCDynamicStore.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
-               1572C4AF0CFB55B400E2776E /* SCDynamicStorePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB691F05C0722B0099E85F /* SCDynamicStorePrivate.h */; settings = {ATTRIBUTES = (Project, Private, ); }; };
+               1572C4AF0CFB55B400E2776E /* SCDynamicStorePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB691F05C0722B0099E85F /* SCDynamicStorePrivate.h */; settings = {ATTRIBUTES = (Private, Project, ); }; };
                1572C4B00CFB55B400E2776E /* SCDynamicStoreKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692105C0722B0099E85F /* SCDynamicStoreKey.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
                1572C4B10CFB55B400E2776E /* SCDynamicStoreCopySpecific.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692305C0722B0099E85F /* SCDynamicStoreCopySpecific.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
-               1572C4B20CFB55B400E2776E /* SCDynamicStoreCopySpecificPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692505C0722B0099E85F /* SCDynamicStoreCopySpecificPrivate.h */; settings = {ATTRIBUTES = (Project, Private, ); }; };
-               1572C4B30CFB55B400E2776E /* SCDynamicStoreSetSpecificPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692705C0722B0099E85F /* SCDynamicStoreSetSpecificPrivate.h */; settings = {ATTRIBUTES = (Project, Private, ); }; };
+               1572C4B20CFB55B400E2776E /* SCDynamicStoreCopySpecificPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692505C0722B0099E85F /* SCDynamicStoreCopySpecificPrivate.h */; settings = {ATTRIBUTES = (Private, Project, ); }; };
+               1572C4B30CFB55B400E2776E /* SCDynamicStoreSetSpecificPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692705C0722B0099E85F /* SCDynamicStoreSetSpecificPrivate.h */; settings = {ATTRIBUTES = (Private, Project, ); }; };
                1572C4B40CFB55B400E2776E /* SCPreferencesInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692905C0722B0099E85F /* SCPreferencesInternal.h */; settings = {ATTRIBUTES = (Project, ); }; };
                1572C4B50CFB55B400E2776E /* SCPreferences.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692B05C0722B0099E85F /* SCPreferences.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
-               1572C4B60CFB55B400E2776E /* SCPreferencesPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692D05C0722B0099E85F /* SCPreferencesPrivate.h */; settings = {ATTRIBUTES = (Project, Private, ); }; };
+               1572C4B60CFB55B400E2776E /* SCPreferencesPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692D05C0722B0099E85F /* SCPreferencesPrivate.h */; settings = {ATTRIBUTES = (Private, Project, ); }; };
                1572C4B70CFB55B400E2776E /* SCPreferencesPath.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692F05C0722B0099E85F /* SCPreferencesPath.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
                1572C4B80CFB55B400E2776E /* SCPreferencesSetSpecific.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB693105C0722B0099E85F /* SCPreferencesSetSpecific.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
                1572C4B90CFB55B400E2776E /* SCNetworkConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 15AD7A380670A85900BFE03C /* SCNetworkConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; };
                1572C4BB0CFB55B400E2776E /* SCNetwork.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB693305C0722B0099E85F /* SCNetwork.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
                1572C4BC0CFB55B400E2776E /* SCNetworkConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB693505C0722B0099E85F /* SCNetworkConnection.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
                1572C4BD0CFB55B400E2776E /* SCNetworkReachability.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB693705C0722B0099E85F /* SCNetworkReachability.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
-               1572C4BE0CFB55B400E2776E /* SCValidation.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB693905C0722B0099E85F /* SCValidation.h */; settings = {ATTRIBUTES = (Project, Private, ); }; };
+               1572C4BE0CFB55B400E2776E /* SCValidation.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB693905C0722B0099E85F /* SCValidation.h */; settings = {ATTRIBUTES = (Private, Project, ); }; };
                1572C4BF0CFB55B400E2776E /* DHCPClientPreferences.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB693D05C0722B0099E85F /* DHCPClientPreferences.h */; settings = {ATTRIBUTES = (Public, ); }; };
                1572C4C00CFB55B400E2776E /* SCDynamicStoreCopyDHCPInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB693F05C0722B0099E85F /* SCDynamicStoreCopyDHCPInfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
                1572C4C10CFB55B400E2776E /* moh_msg.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB694105C0722B0099E85F /* moh_msg.h */; };
                1572C5120CFB55B400E2776E /* dy_framework.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69B405C0722B0099E85F /* dy_framework.c */; settings = {ATTRIBUTES = (); }; };
                1572C5140CFB55B400E2776E /* config.defs in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69BE05C0722B0099E85F /* config.defs */; settings = {ATTRIBUTES = (Client, ); }; };
                1572C5150CFB55B400E2776E /* SCPreferencesPathKey.c in Sources */ = {isa = PBXBuildFile; fileRef = 151BDA5D05D9E2ED00657BC7 /* SCPreferencesPathKey.c */; };
-               1572C5180CFB55B400E2776E /* shared_dns_info.defs in Sources */ = {isa = PBXBuildFile; fileRef = 15FCAAD005FD0EBF00CB79E6 /* shared_dns_info.defs */; settings = {ATTRIBUTES = (Client, ); }; };
                1572C5190CFB55B400E2776E /* SCNetworkConfigurationInternal.c in Sources */ = {isa = PBXBuildFile; fileRef = 15AD7A390670A85900BFE03C /* SCNetworkConfigurationInternal.c */; };
                1572C51A0CFB55B400E2776E /* SCNetworkInterface.c in Sources */ = {isa = PBXBuildFile; fileRef = 15AD7A3B0670A85900BFE03C /* SCNetworkInterface.c */; };
                1572C51B0CFB55B400E2776E /* SCNetworkProtocol.c in Sources */ = {isa = PBXBuildFile; fileRef = 15AD7A3C0670A85900BFE03C /* SCNetworkProtocol.c */; };
                1572C5210CFB55B400E2776E /* SCPreferencesKeychainPrivate.c in Sources */ = {isa = PBXBuildFile; fileRef = 152E68C20A2C89E30011FDA8 /* SCPreferencesKeychainPrivate.c */; };
                1572C5220CFB55B400E2776E /* SCNetworkSignature.c in Sources */ = {isa = PBXBuildFile; fileRef = F95B8A420B03E07A00993BA3 /* SCNetworkSignature.c */; };
                1572C5240CFB55B400E2776E /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15CB6A6F05C0722B0099E85F /* CoreFoundation.framework */; };
+               1572C57F171CCFE200870549 /* pppcontroller_mach_defines.h in Headers */ = {isa = PBXBuildFile; fileRef = 1572C57E171CCF9500870549 /* pppcontroller_mach_defines.h */; };
+               1572C580171CCFF000870549 /* pppcontroller_mach_defines.h in Headers */ = {isa = PBXBuildFile; fileRef = 1572C57E171CCF9500870549 /* pppcontroller_mach_defines.h */; };
+               1572C581171CD00E00870549 /* pppcontroller_mach_defines.h in Headers */ = {isa = PBXBuildFile; fileRef = 1572C57E171CCF9500870549 /* pppcontroller_mach_defines.h */; };
                1572EB7B0A506D3B00D02459 /* smb-configuration.c in Sources */ = {isa = PBXBuildFile; fileRef = 1572EB7A0A506D3B00D02459 /* smb-configuration.c */; };
+               15732A7816EA503200F3AC4C /* configd.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB69CF05C0722B0099E85F /* configd.h */; };
+               15732A7916EA503200F3AC4C /* _SCD.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB69D105C0722B0099E85F /* _SCD.h */; };
+               15732A7A16EA503200F3AC4C /* configd_server.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB69D305C0722B0099E85F /* configd_server.h */; };
+               15732A7B16EA503200F3AC4C /* notify_server.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB69D505C0722B0099E85F /* notify_server.h */; };
+               15732A7C16EA503200F3AC4C /* plugin_support.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB69D705C0722B0099E85F /* plugin_support.h */; };
+               15732A7D16EA503200F3AC4C /* session.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB69D905C0722B0099E85F /* session.h */; };
+               15732A7E16EA503200F3AC4C /* pattern.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB69DB05C0722B0099E85F /* pattern.h */; };
+               15732A8016EA503200F3AC4C /* configd.m in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69E005C0722B0099E85F /* configd.m */; settings = {ATTRIBUTES = (); }; };
+               15732A8116EA503200F3AC4C /* _SCD.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69E205C0722B0099E85F /* _SCD.c */; settings = {ATTRIBUTES = (); }; };
+               15732A8216EA503200F3AC4C /* configd_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69E405C0722B0099E85F /* configd_server.c */; settings = {ATTRIBUTES = (); }; };
+               15732A8316EA503200F3AC4C /* notify_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69E605C0722B0099E85F /* notify_server.c */; settings = {ATTRIBUTES = (); }; };
+               15732A8416EA503200F3AC4C /* plugin_support.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69E805C0722B0099E85F /* plugin_support.c */; settings = {ATTRIBUTES = (); }; };
+               15732A8516EA503200F3AC4C /* session.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69EA05C0722B0099E85F /* session.c */; settings = {ATTRIBUTES = (); }; };
+               15732A8616EA503200F3AC4C /* pattern.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69EC05C0722B0099E85F /* pattern.c */; settings = {ATTRIBUTES = (); }; };
+               15732A8716EA503200F3AC4C /* _configopen.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69F005C0722B0099E85F /* _configopen.c */; settings = {ATTRIBUTES = (); }; };
+               15732A8816EA503200F3AC4C /* _configclose.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69F205C0722B0099E85F /* _configclose.c */; settings = {ATTRIBUTES = (); }; };
+               15732A8916EA503200F3AC4C /* _configunlock.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69F605C0722B0099E85F /* _configunlock.c */; settings = {ATTRIBUTES = (); }; };
+               15732A8A16EA503200F3AC4C /* _configlist.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69F805C0722B0099E85F /* _configlist.c */; settings = {ATTRIBUTES = (); }; };
+               15732A8B16EA503200F3AC4C /* _configadd.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69FA05C0722B0099E85F /* _configadd.c */; settings = {ATTRIBUTES = (); }; };
+               15732A8C16EA503200F3AC4C /* _configget.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69FE05C0722B0099E85F /* _configget.c */; settings = {ATTRIBUTES = (); }; };
+               15732A8D16EA503200F3AC4C /* _configset.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A0005C0722B0099E85F /* _configset.c */; settings = {ATTRIBUTES = (); }; };
+               15732A8E16EA503200F3AC4C /* _configremove.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A0205C0722B0099E85F /* _configremove.c */; settings = {ATTRIBUTES = (); }; };
+               15732A8F16EA503200F3AC4C /* _confignotify.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A0605C0722B0099E85F /* _confignotify.c */; settings = {ATTRIBUTES = (); }; };
+               15732A9016EA503200F3AC4C /* _notifyadd.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A0805C0722B0099E85F /* _notifyadd.c */; settings = {ATTRIBUTES = (); }; };
+               15732A9116EA503200F3AC4C /* _notifyremove.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A0A05C0722B0099E85F /* _notifyremove.c */; settings = {ATTRIBUTES = (); }; };
+               15732A9216EA503200F3AC4C /* _notifychanges.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A0C05C0722B0099E85F /* _notifychanges.c */; settings = {ATTRIBUTES = (); }; };
+               15732A9316EA503200F3AC4C /* _notifyviaport.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A0E05C0722B0099E85F /* _notifyviaport.c */; settings = {ATTRIBUTES = (); }; };
+               15732A9416EA503200F3AC4C /* _notifyviafd.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A1005C0722B0099E85F /* _notifyviafd.c */; settings = {ATTRIBUTES = (); }; };
+               15732A9516EA503200F3AC4C /* _notifyviasignal.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A1205C0722B0099E85F /* _notifyviasignal.c */; settings = {ATTRIBUTES = (); }; };
+               15732A9616EA503200F3AC4C /* _notifycancel.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A1405C0722B0099E85F /* _notifycancel.c */; settings = {ATTRIBUTES = (); }; };
+               15732A9716EA503200F3AC4C /* _snapshot.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A1605C0722B0099E85F /* _snapshot.c */; settings = {ATTRIBUTES = (); }; };
+               15732A9816EA503200F3AC4C /* config.defs in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69BE05C0722B0099E85F /* config.defs */; settings = {ATTRIBUTES = (Server, ); }; };
+               15732A9916EA503200F3AC4C /* dnsinfo_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B73F0D05FD1B670096477F /* dnsinfo_server.c */; };
+               15732A9A16EA503200F3AC4C /* SCNetworkReachabilityServer_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 15C330BB134B92780028E36B /* SCNetworkReachabilityServer_server.c */; };
+               15732A9C16EA503200F3AC4C /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15CB6A6F05C0722B0099E85F /* CoreFoundation.framework */; };
+               15732A9D16EA503200F3AC4C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1547072E0D1F70C80075C28D /* SystemConfiguration.framework */; };
+               15732A9E16EA503200F3AC4C /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1543636A0752D03C00A8EC6C /* IOKit.framework */; };
+               15732A9F16EA503200F3AC4C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1520A3DE0846B2DC0010B584 /* Security.framework */; };
+               15732AA016EA503200F3AC4C /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 15BAA32207F0699A00D9EC95 /* libbsm.dylib */; };
+               15732AAF16EA511900F3AC4C /* scutil.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB6A4305C0722B0099E85F /* scutil.h */; };
+               15732AB016EA511900F3AC4C /* commands.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB6A4505C0722B0099E85F /* commands.h */; };
+               15732AB116EA511900F3AC4C /* dictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB6A4705C0722B0099E85F /* dictionary.h */; };
+               15732AB216EA511900F3AC4C /* session.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB6A4905C0722B0099E85F /* session.h */; };
+               15732AB316EA511900F3AC4C /* cache.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB6A4B05C0722B0099E85F /* cache.h */; };
+               15732AB416EA511900F3AC4C /* notifications.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB6A4D05C0722B0099E85F /* notifications.h */; };
+               15732AB516EA511900F3AC4C /* tests.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB6A4F05C0722B0099E85F /* tests.h */; };
+               15732AB616EA511900F3AC4C /* prefs.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB6A5105C0722B0099E85F /* prefs.h */; };
+               15732AB716EA511900F3AC4C /* net.h in Headers */ = {isa = PBXBuildFile; fileRef = 15A509A406C2518F001F0AB7 /* net.h */; };
+               15732AB816EA511900F3AC4C /* net_interface.h in Headers */ = {isa = PBXBuildFile; fileRef = 15DC34680711D49400A3311C /* net_interface.h */; };
+               15732AB916EA511900F3AC4C /* net_protocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 15DC346A0711D49400A3311C /* net_protocol.h */; };
+               15732ABA16EA511900F3AC4C /* net_service.h in Headers */ = {isa = PBXBuildFile; fileRef = 15DC346C0711D49400A3311C /* net_service.h */; };
+               15732ABB16EA511900F3AC4C /* net_set.h in Headers */ = {isa = PBXBuildFile; fileRef = 15DC346E0711D49400A3311C /* net_set.h */; };
+               15732ABC16EA511900F3AC4C /* nc.h in Headers */ = {isa = PBXBuildFile; fileRef = 72B43726113C7BFC00EBF1B6 /* nc.h */; };
+               15732ABE16EA511900F3AC4C /* scutil.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A5405C0722B0099E85F /* scutil.c */; settings = {ATTRIBUTES = (); }; };
+               15732ABF16EA511900F3AC4C /* commands.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A5605C0722B0099E85F /* commands.c */; settings = {ATTRIBUTES = (); }; };
+               15732AC016EA511900F3AC4C /* dictionary.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A5805C0722B0099E85F /* dictionary.c */; settings = {ATTRIBUTES = (); }; };
+               15732AC116EA511900F3AC4C /* session.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A5A05C0722B0099E85F /* session.c */; settings = {ATTRIBUTES = (); }; };
+               15732AC216EA511900F3AC4C /* cache.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A5C05C0722B0099E85F /* cache.c */; settings = {ATTRIBUTES = (); }; };
+               15732AC316EA511900F3AC4C /* notifications.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A5E05C0722B0099E85F /* notifications.c */; settings = {ATTRIBUTES = (); }; };
+               15732AC416EA511900F3AC4C /* tests.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A6005C0722B0099E85F /* tests.c */; settings = {ATTRIBUTES = (); }; };
+               15732AC516EA511900F3AC4C /* prefs.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A6205C0722B0099E85F /* prefs.c */; settings = {ATTRIBUTES = (); }; };
+               15732AC616EA511900F3AC4C /* net.c in Sources */ = {isa = PBXBuildFile; fileRef = 15A509A306C2518F001F0AB7 /* net.c */; };
+               15732AC716EA511900F3AC4C /* net_interface.c in Sources */ = {isa = PBXBuildFile; fileRef = 15DC34670711D49400A3311C /* net_interface.c */; };
+               15732AC816EA511900F3AC4C /* net_protocol.c in Sources */ = {isa = PBXBuildFile; fileRef = 15DC34690711D49400A3311C /* net_protocol.c */; };
+               15732AC916EA511900F3AC4C /* net_service.c in Sources */ = {isa = PBXBuildFile; fileRef = 15DC346B0711D49400A3311C /* net_service.c */; };
+               15732ACA16EA511900F3AC4C /* net_set.c in Sources */ = {isa = PBXBuildFile; fileRef = 15DC346D0711D49400A3311C /* net_set.c */; };
+               15732ACB16EA511900F3AC4C /* nc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72B43727113C7BFC00EBF1B6 /* nc.c */; };
+               15732ACC16EA511900F3AC4C /* IPMonitorControlPrefs.c in Sources */ = {isa = PBXBuildFile; fileRef = F9A3780E16A4846E00C57CDC /* IPMonitorControlPrefs.c */; };
+               15732ACE16EA511900F3AC4C /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15CB6A6F05C0722B0099E85F /* CoreFoundation.framework */; };
+               15732ACF16EA511900F3AC4C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1547072E0D1F70C80075C28D /* SystemConfiguration.framework */; };
+               15732AD016EA511900F3AC4C /* libedit.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 152CEED0070CF6640050F23C /* libedit.dylib */; };
+               15732AD816EA6B6700F3AC4C /* dnsinfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B73F0905FD1B670096477F /* dnsinfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
+               15732AD916EA6B6700F3AC4C /* network_information.h in Headers */ = {isa = PBXBuildFile; fileRef = D6986A781368913C0091C931 /* network_information.h */; settings = {ATTRIBUTES = (Public, ); }; };
+               15732ADA16EA6B6700F3AC4C /* dnsinfo_private.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B73F0C05FD1B670096477F /* dnsinfo_private.h */; };
+               15732ADB16EA6B6700F3AC4C /* libSystemConfiguration_client.h in Headers */ = {isa = PBXBuildFile; fileRef = 153338BB14BE7978004FCE22 /* libSystemConfiguration_client.h */; };
+               15732ADD16EA6B6700F3AC4C /* dnsinfo_copy.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B73F0805FD1B670096477F /* dnsinfo_copy.c */; };
+               15732ADE16EA6B6700F3AC4C /* network_information.c in Sources */ = {isa = PBXBuildFile; fileRef = D6986A77136891300091C931 /* network_information.c */; };
+               15732ADF16EA6B6700F3AC4C /* libSystemConfiguration_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 153338BA14BE7978004FCE22 /* libSystemConfiguration_client.c */; };
                157433E00D4A8122002ACA73 /* scselect.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A2E05C0722B0099E85F /* scselect.c */; settings = {ATTRIBUTES = (); }; };
                157433E20D4A8122002ACA73 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15CB6A6F05C0722B0099E85F /* CoreFoundation.framework */; };
                157433E30D4A8122002ACA73 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1547072E0D1F70C80075C28D /* SystemConfiguration.framework */; };
                1575FD2812CD15C60003D86E /* proxy-configuration.h in Headers */ = {isa = PBXBuildFile; fileRef = 1575FD2612CD15C60003D86E /* proxy-configuration.h */; };
                1575FD2912CD15C60003D86E /* proxy-configuration.c in Sources */ = {isa = PBXBuildFile; fileRef = 1575FD2512CD15C60003D86E /* proxy-configuration.c */; };
                1575FD2A12CD15C60003D86E /* proxy-configuration.h in Headers */ = {isa = PBXBuildFile; fileRef = 1575FD2612CD15C60003D86E /* proxy-configuration.h */; };
-               1575FD2B12CD15C60003D86E /* proxy-configuration.c in Sources */ = {isa = PBXBuildFile; fileRef = 1575FD2512CD15C60003D86E /* proxy-configuration.c */; };
-               1575FD2C12CD15C60003D86E /* proxy-configuration.h in Headers */ = {isa = PBXBuildFile; fileRef = 1575FD2612CD15C60003D86E /* proxy-configuration.h */; };
                15792B9B0DA2C190008DDED9 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1543636A0752D03C00A8EC6C /* IOKit.framework */; };
                157A84DA0D56C63900B6F1A0 /* dnsinfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B73F0905FD1B670096477F /* dnsinfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
                157A84DB0D56C63900B6F1A0 /* dnsinfo_private.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B73F0C05FD1B670096477F /* dnsinfo_private.h */; };
-               157A84DE0D56C63900B6F1A0 /* shared_dns_info.defs in Sources */ = {isa = PBXBuildFile; fileRef = 15FCAAD005FD0EBF00CB79E6 /* shared_dns_info.defs */; settings = {ATTRIBUTES = (Client, ); }; };
                157A84DF0D56C63900B6F1A0 /* dnsinfo_copy.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B73F0805FD1B670096477F /* dnsinfo_copy.c */; };
-               157A84E00D56C63900B6F1A0 /* dnsinfo_private.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B73F0B05FD1B670096477F /* dnsinfo_private.c */; };
                157A84F60D56C7E800B6F1A0 /* dns-configuration.h in Headers */ = {isa = PBXBuildFile; fileRef = 155D22380AF13A7300D52ED0 /* dns-configuration.h */; };
                157A84F70D56C7E800B6F1A0 /* set-hostname.h in Headers */ = {isa = PBXBuildFile; fileRef = 155D22390AF13A7300D52ED0 /* set-hostname.h */; };
                157A84FB0D56C7E800B6F1A0 /* dns-configuration.c in Sources */ = {isa = PBXBuildFile; fileRef = 159D53AA07528B36004F8947 /* dns-configuration.c */; };
                158317450CFB80A1006F62B9 /* _notifycancel.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A1405C0722B0099E85F /* _notifycancel.c */; settings = {ATTRIBUTES = (); }; };
                158317460CFB80A1006F62B9 /* _snapshot.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A1605C0722B0099E85F /* _snapshot.c */; settings = {ATTRIBUTES = (); }; };
                158317470CFB80A1006F62B9 /* config.defs in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69BE05C0722B0099E85F /* config.defs */; settings = {ATTRIBUTES = (Server, ); }; };
-               158317480CFB80A1006F62B9 /* dnsinfo_private.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B73F0B05FD1B670096477F /* dnsinfo_private.c */; };
                158317490CFB80A1006F62B9 /* dnsinfo_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B73F0D05FD1B670096477F /* dnsinfo_server.c */; };
-               1583174A0CFB80A1006F62B9 /* shared_dns_info.defs in Sources */ = {isa = PBXBuildFile; fileRef = 15FCAAD005FD0EBF00CB79E6 /* shared_dns_info.defs */; settings = {ATTRIBUTES = (Server, ); }; };
                1583174C0CFB80A1006F62B9 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15CB6A6F05C0722B0099E85F /* CoreFoundation.framework */; };
                1583174E0CFB80A1006F62B9 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1543636A0752D03C00A8EC6C /* IOKit.framework */; };
                158317500CFB80A1006F62B9 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 15BAA32207F0699A00D9EC95 /* libbsm.dylib */; };
                158337A00CFB6B9E0033AB93 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15CB6A6F05C0722B0099E85F /* CoreFoundation.framework */; };
                158337A20CFB6B9E0033AB93 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1520A3DE0846B2DC0010B584 /* Security.framework */; };
                158337AD0CFB6BDC0033AB93 /* com.apple.SCHelper-embedded.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 151356AD0CE0CF2F0017E523 /* com.apple.SCHelper-embedded.plist */; };
-               1583EA06108395BB00A3BC0C /* dnsinfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B73F0905FD1B670096477F /* dnsinfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
-               1583EA07108395BB00A3BC0C /* dnsinfo_private.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B73F0C05FD1B670096477F /* dnsinfo_private.h */; };
-               1583EA09108395BB00A3BC0C /* shared_dns_info.defs in Sources */ = {isa = PBXBuildFile; fileRef = 15FCAAD005FD0EBF00CB79E6 /* shared_dns_info.defs */; settings = {ATTRIBUTES = (Client, ); }; };
-               1583EA0A108395BB00A3BC0C /* dnsinfo_copy.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B73F0805FD1B670096477F /* dnsinfo_copy.c */; };
-               1583EA0B108395BB00A3BC0C /* dnsinfo_private.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B73F0B05FD1B670096477F /* dnsinfo_private.c */; };
-               1583EA1B108395BB00A3BC0C /* SCSchemaDefinitions.h in Headers */ = {isa = PBXBuildFile; fileRef = 150607DE075A00A300B147BA /* SCSchemaDefinitions.h */; settings = {ATTRIBUTES = (Public, ); }; };
-               1583EA1C108395BB00A3BC0C /* SystemConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB691305C0722B0099E85F /* SystemConfiguration.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
-               1583EA1D108395BB00A3BC0C /* SCPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB691505C0722B0099E85F /* SCPrivate.h */; settings = {ATTRIBUTES = (Project, Private, ); }; };
-               1583EA1E108395BB00A3BC0C /* SCDPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB691705C0722B0099E85F /* SCDPlugin.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               1583EA1F108395BB00A3BC0C /* SCDynamicStoreInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB691B05C0722B0099E85F /* SCDynamicStoreInternal.h */; settings = {ATTRIBUTES = (Project, ); }; };
-               1583EA20108395BB00A3BC0C /* SCDynamicStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB691D05C0722B0099E85F /* SCDynamicStore.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
-               1583EA21108395BB00A3BC0C /* SCDynamicStorePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB691F05C0722B0099E85F /* SCDynamicStorePrivate.h */; settings = {ATTRIBUTES = (Project, Private, ); }; };
-               1583EA22108395BB00A3BC0C /* SCDynamicStoreKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692105C0722B0099E85F /* SCDynamicStoreKey.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
-               1583EA23108395BB00A3BC0C /* SCDynamicStoreCopySpecific.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692305C0722B0099E85F /* SCDynamicStoreCopySpecific.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
-               1583EA24108395BB00A3BC0C /* SCDynamicStoreCopySpecificPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692505C0722B0099E85F /* SCDynamicStoreCopySpecificPrivate.h */; settings = {ATTRIBUTES = (Project, Private, ); }; };
-               1583EA25108395BB00A3BC0C /* SCDynamicStoreSetSpecificPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692705C0722B0099E85F /* SCDynamicStoreSetSpecificPrivate.h */; settings = {ATTRIBUTES = (Project, Private, ); }; };
-               1583EA26108395BB00A3BC0C /* SCPreferencesInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692905C0722B0099E85F /* SCPreferencesInternal.h */; settings = {ATTRIBUTES = (Project, ); }; };
-               1583EA27108395BB00A3BC0C /* SCPreferences.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692B05C0722B0099E85F /* SCPreferences.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
-               1583EA28108395BB00A3BC0C /* SCPreferencesPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692D05C0722B0099E85F /* SCPreferencesPrivate.h */; settings = {ATTRIBUTES = (Project, Private, ); }; };
-               1583EA29108395BB00A3BC0C /* SCPreferencesPath.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692F05C0722B0099E85F /* SCPreferencesPath.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
-               1583EA2A108395BB00A3BC0C /* SCPreferencesSetSpecific.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB693105C0722B0099E85F /* SCPreferencesSetSpecific.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
-               1583EA2B108395BB00A3BC0C /* SCNetworkConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 15AD7A380670A85900BFE03C /* SCNetworkConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; };
-               1583EA2C108395BB00A3BC0C /* SCNetworkConfigurationInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 15AD7A3A0670A85900BFE03C /* SCNetworkConfigurationInternal.h */; settings = {ATTRIBUTES = (); }; };
-               1583EA2D108395BB00A3BC0C /* SCNetwork.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB693305C0722B0099E85F /* SCNetwork.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
-               1583EA2E108395BB00A3BC0C /* SCNetworkConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB693505C0722B0099E85F /* SCNetworkConnection.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
-               1583EA2F108395BB00A3BC0C /* SCNetworkReachability.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB693705C0722B0099E85F /* SCNetworkReachability.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
-               1583EA30108395BB00A3BC0C /* SCValidation.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB693905C0722B0099E85F /* SCValidation.h */; settings = {ATTRIBUTES = (Project, Private, ); }; };
-               1583EA31108395BB00A3BC0C /* DHCPClientPreferences.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB693D05C0722B0099E85F /* DHCPClientPreferences.h */; settings = {ATTRIBUTES = (Public, ); }; };
-               1583EA32108395BB00A3BC0C /* SCDynamicStoreCopyDHCPInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB693F05C0722B0099E85F /* SCDynamicStoreCopyDHCPInfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
-               1583EA33108395BB00A3BC0C /* moh_msg.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB694105C0722B0099E85F /* moh_msg.h */; };
-               1583EA34108395BB00A3BC0C /* moh.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB694305C0722B0099E85F /* moh.h */; };
-               1583EA35108395BB00A3BC0C /* DeviceOnHold.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB694505C0722B0099E85F /* DeviceOnHold.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               1583EA36108395BB00A3BC0C /* dy_framework.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB694905C0722B0099E85F /* dy_framework.h */; };
-               1583EA37108395BB00A3BC0C /* SCPreferencesPathKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 151BDA2B05D9E28B00657BC7 /* SCPreferencesPathKey.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               1583EA38108395BB00A3BC0C /* pppcontroller_types.h in Headers */ = {isa = PBXBuildFile; fileRef = 23C1E2B4062DD2C700835B54 /* pppcontroller_types.h */; };
-               1583EA39108395BB00A3BC0C /* pppcontroller.h in Headers */ = {isa = PBXBuildFile; fileRef = 23C1E2BE062DD5DB00835B54 /* pppcontroller.h */; };
-               1583EA3A108395BB00A3BC0C /* SCPreferencesSetSpecificPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 156BD6BB07E0DFA9008698FF /* SCPreferencesSetSpecificPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               1583EA3B108395BB00A3BC0C /* SCPreferencesGetSpecificPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 154CF3F307E1EA4D00D8302E /* SCPreferencesGetSpecificPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               1583EA3C108395BB00A3BC0C /* SCNetworkConfigurationPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 155A1E6B081079CC00F70D98 /* SCNetworkConfigurationPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               1583EA3E108395BB00A3BC0C /* SCHelper_client.h in Headers */ = {isa = PBXBuildFile; fileRef = 155B7BF60847776D00F0E262 /* SCHelper_client.h */; };
-               1583EA3F108395BB00A3BC0C /* SCNetworkConnectionPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15A2972E0A13C08C009879B3 /* SCNetworkConnectionPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               1583EA40108395BB00A3BC0C /* SCPreferencesKeychainPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 152E68C00A2C89C70011FDA8 /* SCPreferencesKeychainPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               1583EA41108395BB00A3BC0C /* SCSchemaDefinitionsPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 157A88880A470D0F003A4256 /* SCSchemaDefinitionsPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               1583EA42108395BB00A3BC0C /* SCNetworkSignature.h in Headers */ = {isa = PBXBuildFile; fileRef = F95B8A440B03E09300993BA3 /* SCNetworkSignature.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               1583EA43108395BB00A3BC0C /* SCNetworkSignaturePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = F95B8A450B03E09300993BA3 /* SCNetworkSignaturePrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               1583EA44108395BB00A3BC0C /* CaptiveNetwork.h in Headers */ = {isa = PBXBuildFile; fileRef = 15A1FF3010597F17004C9CC9 /* CaptiveNetwork.h */; settings = {ATTRIBUTES = (Public, ); }; };
-               1583EA4B108395BB00A3BC0C /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 15A6F7C20A4B266D00B907EA /* Localizable.strings */; };
-               1583EA4C108395BB00A3BC0C /* NetworkInterface.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1577253606EFBF3100D7B52B /* NetworkInterface.strings */; };
-               1583EA4D108395BB00A3BC0C /* NetworkConfiguration.plist in Resources */ = {isa = PBXBuildFile; fileRef = 15B686220678B65C00FF4023 /* NetworkConfiguration.plist */; };
-               1583EA4E108395BB00A3BC0C /* get-mobility-info in Resources */ = {isa = PBXBuildFile; fileRef = 15CFC229068B222F00123568 /* get-mobility-info */; };
-               1583EA50108395BB00A3BC0C /* SCSchemaDefinitions.c in Sources */ = {isa = PBXBuildFile; fileRef = 150607BD075A00A200B147BA /* SCSchemaDefinitions.c */; };
-               1583EA51108395BB00A3BC0C /* SCD.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB695005C0722B0099E85F /* SCD.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA52108395BB00A3BC0C /* SCDKeys.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB695205C0722B0099E85F /* SCDKeys.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA53108395BB00A3BC0C /* SCDPrivate.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB695405C0722B0099E85F /* SCDPrivate.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA54108395BB00A3BC0C /* SCDPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB695605C0722B0099E85F /* SCDPlugin.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA55108395BB00A3BC0C /* SCDOpen.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB695805C0722B0099E85F /* SCDOpen.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA58108395BB00A3BC0C /* SCDList.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB695E05C0722B0099E85F /* SCDList.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA59108395BB00A3BC0C /* SCDAdd.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB696005C0722B0099E85F /* SCDAdd.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA5A108395BB00A3BC0C /* SCDGet.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB696405C0722B0099E85F /* SCDGet.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA5B108395BB00A3BC0C /* SCDSet.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB696605C0722B0099E85F /* SCDSet.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA5C108395BB00A3BC0C /* SCDRemove.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB696805C0722B0099E85F /* SCDRemove.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA5E108395BB00A3BC0C /* SCDNotify.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB696C05C0722B0099E85F /* SCDNotify.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA5F108395BB00A3BC0C /* SCDNotifierSetKeys.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB696E05C0722B0099E85F /* SCDNotifierSetKeys.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA60108395BB00A3BC0C /* SCDNotifierAdd.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697005C0722B0099E85F /* SCDNotifierAdd.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA61108395BB00A3BC0C /* SCDNotifierRemove.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697205C0722B0099E85F /* SCDNotifierRemove.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA62108395BB00A3BC0C /* SCDNotifierGetChanges.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697405C0722B0099E85F /* SCDNotifierGetChanges.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA63108395BB00A3BC0C /* SCDNotifierWait.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697605C0722B0099E85F /* SCDNotifierWait.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA64108395BB00A3BC0C /* SCDNotifierInformViaCallback.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697805C0722B0099E85F /* SCDNotifierInformViaCallback.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA66108395BB00A3BC0C /* SCDNotifierInformViaFD.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697C05C0722B0099E85F /* SCDNotifierInformViaFD.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA67108395BB00A3BC0C /* SCDNotifierInformViaSignal.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697E05C0722B0099E85F /* SCDNotifierInformViaSignal.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA68108395BB00A3BC0C /* SCDNotifierCancel.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB698005C0722B0099E85F /* SCDNotifierCancel.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA69108395BB00A3BC0C /* SCDSnapshot.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB698205C0722B0099E85F /* SCDSnapshot.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA6A108395BB00A3BC0C /* SCP.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB698405C0722B0099E85F /* SCP.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA6B108395BB00A3BC0C /* SCPOpen.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB698605C0722B0099E85F /* SCPOpen.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA6C108395BB00A3BC0C /* SCPLock.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB698805C0722B0099E85F /* SCPLock.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA6D108395BB00A3BC0C /* SCPUnlock.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB698A05C0722B0099E85F /* SCPUnlock.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA6E108395BB00A3BC0C /* SCPList.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB698C05C0722B0099E85F /* SCPList.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA6F108395BB00A3BC0C /* SCPGet.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB698E05C0722B0099E85F /* SCPGet.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA70108395BB00A3BC0C /* SCPAdd.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB699005C0722B0099E85F /* SCPAdd.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA71108395BB00A3BC0C /* SCPSet.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB699205C0722B0099E85F /* SCPSet.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA72108395BB00A3BC0C /* SCPRemove.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB699405C0722B0099E85F /* SCPRemove.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA73108395BB00A3BC0C /* SCPCommit.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB699605C0722B0099E85F /* SCPCommit.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA74108395BB00A3BC0C /* SCPApply.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB699805C0722B0099E85F /* SCPApply.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA75108395BB00A3BC0C /* SCPPath.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB699A05C0722B0099E85F /* SCPPath.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA76108395BB00A3BC0C /* SCDHostName.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB699E05C0722B0099E85F /* SCDHostName.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA77108395BB00A3BC0C /* SCLocation.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69A005C0722B0099E85F /* SCLocation.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA78108395BB00A3BC0C /* SCNetwork.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69A205C0722B0099E85F /* SCNetwork.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA79108395BB00A3BC0C /* pppcontroller.defs in Sources */ = {isa = PBXBuildFile; fileRef = 23C1E2B8062DD45900835B54 /* pppcontroller.defs */; settings = {ATTRIBUTES = (Client, ); }; };
-               1583EA7A108395BB00A3BC0C /* SCNetworkConnection.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69A405C0722B0099E85F /* SCNetworkConnection.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA7B108395BB00A3BC0C /* SCNetworkConnectionPrivate.c in Sources */ = {isa = PBXBuildFile; fileRef = 15A2972D0A13C08C009879B3 /* SCNetworkConnectionPrivate.c */; };
-               1583EA7C108395BB00A3BC0C /* SCNetworkReachability.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69A605C0722B0099E85F /* SCNetworkReachability.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA7D108395BB00A3BC0C /* SCProxies.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69A805C0722B0099E85F /* SCProxies.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA7E108395BB00A3BC0C /* DHCP.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69AC05C0722B0099E85F /* DHCP.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA7F108395BB00A3BC0C /* moh.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69AE05C0722B0099E85F /* moh.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA80108395BB00A3BC0C /* DeviceOnHold.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69B005C0722B0099E85F /* DeviceOnHold.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA81108395BB00A3BC0C /* LinkConfiguration.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69B205C0722B0099E85F /* LinkConfiguration.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA82108395BB00A3BC0C /* dy_framework.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69B405C0722B0099E85F /* dy_framework.c */; settings = {ATTRIBUTES = (); }; };
-               1583EA83108395BB00A3BC0C /* config.defs in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69BE05C0722B0099E85F /* config.defs */; settings = {ATTRIBUTES = (Client, ); }; };
-               1583EA84108395BB00A3BC0C /* SCPreferencesPathKey.c in Sources */ = {isa = PBXBuildFile; fileRef = 151BDA5D05D9E2ED00657BC7 /* SCPreferencesPathKey.c */; };
-               1583EA85108395BB00A3BC0C /* shared_dns_info.defs in Sources */ = {isa = PBXBuildFile; fileRef = 15FCAAD005FD0EBF00CB79E6 /* shared_dns_info.defs */; settings = {ATTRIBUTES = (Client, ); }; };
-               1583EA86108395BB00A3BC0C /* SCNetworkConfigurationInternal.c in Sources */ = {isa = PBXBuildFile; fileRef = 15AD7A390670A85900BFE03C /* SCNetworkConfigurationInternal.c */; };
-               1583EA87108395BB00A3BC0C /* SCNetworkInterface.c in Sources */ = {isa = PBXBuildFile; fileRef = 15AD7A3B0670A85900BFE03C /* SCNetworkInterface.c */; };
-               1583EA88108395BB00A3BC0C /* SCNetworkProtocol.c in Sources */ = {isa = PBXBuildFile; fileRef = 15AD7A3C0670A85900BFE03C /* SCNetworkProtocol.c */; };
-               1583EA89108395BB00A3BC0C /* SCNetworkService.c in Sources */ = {isa = PBXBuildFile; fileRef = 15AD7A3D0670A85900BFE03C /* SCNetworkService.c */; };
-               1583EA8A108395BB00A3BC0C /* SCNetworkSet.c in Sources */ = {isa = PBXBuildFile; fileRef = 15AD7A3E0670A85900BFE03C /* SCNetworkSet.c */; };
-               1583EA8C108395BB00A3BC0C /* SCHelper_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 15DAF2D808466D4900D1B2BD /* SCHelper_client.c */; };
-               1583EA8D108395BB00A3BC0C /* SCPreferencesKeychainPrivate.c in Sources */ = {isa = PBXBuildFile; fileRef = 152E68C20A2C89E30011FDA8 /* SCPreferencesKeychainPrivate.c */; };
-               1583EA8E108395BB00A3BC0C /* SCNetworkSignature.c in Sources */ = {isa = PBXBuildFile; fileRef = F95B8A420B03E07A00993BA3 /* SCNetworkSignature.c */; };
-               1583EA8F108395BB00A3BC0C /* CaptiveNetwork.c in Sources */ = {isa = PBXBuildFile; fileRef = 15A1FF3110597F17004C9CC9 /* CaptiveNetwork.c */; };
-               1583EA94108395BB00A3BC0C /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15CB6A6F05C0722B0099E85F /* CoreFoundation.framework */; };
-               1583EA9E108395BB00A3BC0C /* SCHelper_client.h in Headers */ = {isa = PBXBuildFile; fileRef = 155B7BF60847776D00F0E262 /* SCHelper_client.h */; };
-               1583EAA0108395BB00A3BC0C /* SCHelper_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 15DAF2D908466D4900D1B2BD /* SCHelper_server.c */; };
-               1583EAA2108395BB00A3BC0C /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15CB6A6F05C0722B0099E85F /* CoreFoundation.framework */; };
-               1583EAA3108395BB00A3BC0C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1547072E0D1F70C80075C28D /* SystemConfiguration.framework */; };
-               1583EAA4108395BB00A3BC0C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1520A3DE0846B2DC0010B584 /* Security.framework */; };
-               1583EAA6108395BB00A3BC0C /* com.apple.SCHelper-embedded.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 151356AD0CE0CF2F0017E523 /* com.apple.SCHelper-embedded.plist */; };
-               1583EACC108395BB00A3BC0C /* dns-configuration.h in Headers */ = {isa = PBXBuildFile; fileRef = 155D22380AF13A7300D52ED0 /* dns-configuration.h */; };
-               1583EACD108395BB00A3BC0C /* set-hostname.h in Headers */ = {isa = PBXBuildFile; fileRef = 155D22390AF13A7300D52ED0 /* set-hostname.h */; };
-               1583EACE108395BB00A3BC0C /* dnsinfo_create.h in Headers */ = {isa = PBXBuildFile; fileRef = 1532629006281C9D00B1C10C /* dnsinfo_create.h */; };
-               1583EAD0108395BB00A3BC0C /* ip_plugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 159D53A707528B36004F8947 /* ip_plugin.c */; };
-               1583EAD1108395BB00A3BC0C /* dns-configuration.c in Sources */ = {isa = PBXBuildFile; fileRef = 159D53AA07528B36004F8947 /* dns-configuration.c */; };
-               1583EAD2108395BB00A3BC0C /* set-hostname.c in Sources */ = {isa = PBXBuildFile; fileRef = 159D53AB07528B36004F8947 /* set-hostname.c */; };
-               1583EAD3108395BB00A3BC0C /* dnsinfo_create.c in Sources */ = {isa = PBXBuildFile; fileRef = 1521FC5C060F296A003B28F5 /* dnsinfo_create.c */; };
-               1583EAD4108395BB00A3BC0C /* shared_dns_info.defs in Sources */ = {isa = PBXBuildFile; fileRef = 15FCAAD005FD0EBF00CB79E6 /* shared_dns_info.defs */; };
-               1583EAE3108395BB00A3BC0C /* ifnamer.c in Sources */ = {isa = PBXBuildFile; fileRef = 159D53AE07528B36004F8947 /* ifnamer.c */; };
-               1583EAF1108395BC00A3BC0C /* cache.h in Headers */ = {isa = PBXBuildFile; fileRef = 159D53CB07528B36004F8947 /* cache.h */; };
-               1583EAF2108395BC00A3BC0C /* ev_dlil.h in Headers */ = {isa = PBXBuildFile; fileRef = 159D53B207528B36004F8947 /* ev_dlil.h */; };
-               1583EAF3108395BC00A3BC0C /* ev_ipv4.h in Headers */ = {isa = PBXBuildFile; fileRef = 159D53B807528B36004F8947 /* ev_ipv4.h */; };
-               1583EAF4108395BC00A3BC0C /* ev_ipv6.h in Headers */ = {isa = PBXBuildFile; fileRef = 159D53BA07528B36004F8947 /* ev_ipv6.h */; };
-               1583EAF5108395BC00A3BC0C /* eventmon.h in Headers */ = {isa = PBXBuildFile; fileRef = 159D53B707528B36004F8947 /* eventmon.h */; };
-               1583EAF7108395BC00A3BC0C /* cache.c in Sources */ = {isa = PBXBuildFile; fileRef = 159D53CA07528B36004F8947 /* cache.c */; };
-               1583EAF8108395BC00A3BC0C /* ev_dlil.c in Sources */ = {isa = PBXBuildFile; fileRef = 159D53B107528B36004F8947 /* ev_dlil.c */; };
-               1583EAF9108395BC00A3BC0C /* ev_ipv4.c in Sources */ = {isa = PBXBuildFile; fileRef = 159D53B307528B36004F8947 /* ev_ipv4.c */; };
-               1583EAFA108395BC00A3BC0C /* ev_ipv6.c in Sources */ = {isa = PBXBuildFile; fileRef = 159D53B407528B36004F8947 /* ev_ipv6.c */; };
-               1583EAFB108395BC00A3BC0C /* eventmon.c in Sources */ = {isa = PBXBuildFile; fileRef = 159D53B007528B36004F8947 /* eventmon.c */; };
-               1583EB0A108395BC00A3BC0C /* linkconfig.c in Sources */ = {isa = PBXBuildFile; fileRef = 159D53C107528B36004F8947 /* linkconfig.c */; };
-               1583EB18108395BC00A3BC0C /* logger.c in Sources */ = {isa = PBXBuildFile; fileRef = 1531D3DB0E93E6DA00248432 /* logger.c */; };
-               1583EB1A108395BC00A3BC0C /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15CB6A6F05C0722B0099E85F /* CoreFoundation.framework */; };
-               1583EB1B108395BC00A3BC0C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1559C4440D349A4E0098FD59 /* SystemConfiguration.framework */; };
-               1583EB1C108395BC00A3BC0C /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1543636A0752D03C00A8EC6C /* IOKit.framework */; };
-               1583EB35108395BD00A3BC0C /* prefsmon.c in Sources */ = {isa = PBXBuildFile; fileRef = 159D53C307528B36004F8947 /* prefsmon.c */; };
-               1583EB4D108395BD00A3BC0C /* configd.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB69CF05C0722B0099E85F /* configd.h */; };
-               1583EB4E108395BD00A3BC0C /* _SCD.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB69D105C0722B0099E85F /* _SCD.h */; };
-               1583EB4F108395BD00A3BC0C /* configd_server.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB69D305C0722B0099E85F /* configd_server.h */; };
-               1583EB50108395BD00A3BC0C /* notify_server.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB69D505C0722B0099E85F /* notify_server.h */; };
-               1583EB51108395BD00A3BC0C /* plugin_support.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB69D705C0722B0099E85F /* plugin_support.h */; };
-               1583EB52108395BD00A3BC0C /* session.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB69D905C0722B0099E85F /* session.h */; };
-               1583EB53108395BD00A3BC0C /* pattern.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB69DB05C0722B0099E85F /* pattern.h */; };
-               1583EB55108395BD00A3BC0C /* configd.m in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69E005C0722B0099E85F /* configd.m */; settings = {ATTRIBUTES = (); }; };
-               1583EB56108395BD00A3BC0C /* _SCD.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69E205C0722B0099E85F /* _SCD.c */; settings = {ATTRIBUTES = (); }; };
-               1583EB57108395BD00A3BC0C /* configd_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69E405C0722B0099E85F /* configd_server.c */; settings = {ATTRIBUTES = (); }; };
-               1583EB58108395BD00A3BC0C /* notify_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69E605C0722B0099E85F /* notify_server.c */; settings = {ATTRIBUTES = (); }; };
-               1583EB59108395BD00A3BC0C /* plugin_support.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69E805C0722B0099E85F /* plugin_support.c */; settings = {ATTRIBUTES = (); }; };
-               1583EB5A108395BD00A3BC0C /* session.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69EA05C0722B0099E85F /* session.c */; settings = {ATTRIBUTES = (); }; };
-               1583EB5B108395BD00A3BC0C /* pattern.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69EC05C0722B0099E85F /* pattern.c */; settings = {ATTRIBUTES = (); }; };
-               1583EB5C108395BD00A3BC0C /* _configopen.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69F005C0722B0099E85F /* _configopen.c */; settings = {ATTRIBUTES = (); }; };
-               1583EB5D108395BD00A3BC0C /* _configclose.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69F205C0722B0099E85F /* _configclose.c */; settings = {ATTRIBUTES = (); }; };
-               1583EB5F108395BD00A3BC0C /* _configunlock.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69F605C0722B0099E85F /* _configunlock.c */; settings = {ATTRIBUTES = (); }; };
-               1583EB60108395BD00A3BC0C /* _configlist.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69F805C0722B0099E85F /* _configlist.c */; settings = {ATTRIBUTES = (); }; };
-               1583EB61108395BD00A3BC0C /* _configadd.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69FA05C0722B0099E85F /* _configadd.c */; settings = {ATTRIBUTES = (); }; };
-               1583EB62108395BD00A3BC0C /* _configget.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69FE05C0722B0099E85F /* _configget.c */; settings = {ATTRIBUTES = (); }; };
-               1583EB63108395BD00A3BC0C /* _configset.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A0005C0722B0099E85F /* _configset.c */; settings = {ATTRIBUTES = (); }; };
-               1583EB64108395BD00A3BC0C /* _configremove.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A0205C0722B0099E85F /* _configremove.c */; settings = {ATTRIBUTES = (); }; };
-               1583EB66108395BD00A3BC0C /* _confignotify.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A0605C0722B0099E85F /* _confignotify.c */; settings = {ATTRIBUTES = (); }; };
-               1583EB67108395BD00A3BC0C /* _notifyadd.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A0805C0722B0099E85F /* _notifyadd.c */; settings = {ATTRIBUTES = (); }; };
-               1583EB68108395BD00A3BC0C /* _notifyremove.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A0A05C0722B0099E85F /* _notifyremove.c */; settings = {ATTRIBUTES = (); }; };
-               1583EB69108395BD00A3BC0C /* _notifychanges.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A0C05C0722B0099E85F /* _notifychanges.c */; settings = {ATTRIBUTES = (); }; };
-               1583EB6A108395BD00A3BC0C /* _notifyviaport.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A0E05C0722B0099E85F /* _notifyviaport.c */; settings = {ATTRIBUTES = (); }; };
-               1583EB6B108395BD00A3BC0C /* _notifyviafd.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A1005C0722B0099E85F /* _notifyviafd.c */; settings = {ATTRIBUTES = (); }; };
-               1583EB6C108395BD00A3BC0C /* _notifyviasignal.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A1205C0722B0099E85F /* _notifyviasignal.c */; settings = {ATTRIBUTES = (); }; };
-               1583EB6D108395BD00A3BC0C /* _notifycancel.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A1405C0722B0099E85F /* _notifycancel.c */; settings = {ATTRIBUTES = (); }; };
-               1583EB6E108395BD00A3BC0C /* _snapshot.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A1605C0722B0099E85F /* _snapshot.c */; settings = {ATTRIBUTES = (); }; };
-               1583EB6F108395BD00A3BC0C /* config.defs in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69BE05C0722B0099E85F /* config.defs */; settings = {ATTRIBUTES = (Server, ); }; };
-               1583EB70108395BD00A3BC0C /* dnsinfo_private.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B73F0B05FD1B670096477F /* dnsinfo_private.c */; };
-               1583EB71108395BD00A3BC0C /* dnsinfo_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B73F0D05FD1B670096477F /* dnsinfo_server.c */; };
-               1583EB72108395BD00A3BC0C /* shared_dns_info.defs in Sources */ = {isa = PBXBuildFile; fileRef = 15FCAAD005FD0EBF00CB79E6 /* shared_dns_info.defs */; settings = {ATTRIBUTES = (Server, ); }; };
-               1583EB74108395BD00A3BC0C /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15CB6A6F05C0722B0099E85F /* CoreFoundation.framework */; };
-               1583EB75108395BD00A3BC0C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1547072E0D1F70C80075C28D /* SystemConfiguration.framework */; };
-               1583EB76108395BD00A3BC0C /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1543636A0752D03C00A8EC6C /* IOKit.framework */; };
-               1583EB77108395BD00A3BC0C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1520A3DE0846B2DC0010B584 /* Security.framework */; };
-               1583EB78108395BD00A3BC0C /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 15BAA32207F0699A00D9EC95 /* libbsm.dylib */; };
-               1583EB79108395BD00A3BC0C /* libKernelEventMonitor.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 159D53D407528BDA004F8947 /* libKernelEventMonitor.a */; };
-               1583EB7A108395BD00A3BC0C /* libInterfaceNamer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 159D53E507528C4A004F8947 /* libInterfaceNamer.a */; };
-               1583EB7B108395BD00A3BC0C /* libIPMonitor.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 159D53EC07528C61004F8947 /* libIPMonitor.a */; };
-               1583EB7C108395BD00A3BC0C /* libLinkConfiguration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 159D53F307528C79004F8947 /* libLinkConfiguration.a */; };
-               1583EB7E108395BD00A3BC0C /* libPreferencesMonitor.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 159D53FA07528C95004F8947 /* libPreferencesMonitor.a */; };
-               1583EB80108395BD00A3BC0C /* com.apple.configd.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1540E3600987DA9500157C07 /* com.apple.configd.plist */; };
-               1583EB89108395BE00A3BC0C /* scselect.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A2E05C0722B0099E85F /* scselect.c */; settings = {ATTRIBUTES = (); }; };
-               1583EB8B108395BE00A3BC0C /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15CB6A6F05C0722B0099E85F /* CoreFoundation.framework */; };
-               1583EB8C108395BE00A3BC0C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1547072E0D1F70C80075C28D /* SystemConfiguration.framework */; };
-               1583EB94108395BE00A3BC0C /* scutil.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB6A4305C0722B0099E85F /* scutil.h */; };
-               1583EB95108395BE00A3BC0C /* commands.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB6A4505C0722B0099E85F /* commands.h */; };
-               1583EB96108395BE00A3BC0C /* dictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB6A4705C0722B0099E85F /* dictionary.h */; };
-               1583EB97108395BE00A3BC0C /* session.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB6A4905C0722B0099E85F /* session.h */; };
-               1583EB98108395BE00A3BC0C /* cache.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB6A4B05C0722B0099E85F /* cache.h */; };
-               1583EB99108395BE00A3BC0C /* notifications.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB6A4D05C0722B0099E85F /* notifications.h */; };
-               1583EB9A108395BE00A3BC0C /* tests.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB6A4F05C0722B0099E85F /* tests.h */; };
-               1583EB9B108395BE00A3BC0C /* prefs.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB6A5105C0722B0099E85F /* prefs.h */; };
-               1583EB9C108395BE00A3BC0C /* net.h in Headers */ = {isa = PBXBuildFile; fileRef = 15A509A406C2518F001F0AB7 /* net.h */; };
-               1583EB9D108395BE00A3BC0C /* net_interface.h in Headers */ = {isa = PBXBuildFile; fileRef = 15DC34680711D49400A3311C /* net_interface.h */; };
-               1583EB9E108395BE00A3BC0C /* net_protocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 15DC346A0711D49400A3311C /* net_protocol.h */; };
-               1583EB9F108395BE00A3BC0C /* net_service.h in Headers */ = {isa = PBXBuildFile; fileRef = 15DC346C0711D49400A3311C /* net_service.h */; };
-               1583EBA0108395BE00A3BC0C /* net_set.h in Headers */ = {isa = PBXBuildFile; fileRef = 15DC346E0711D49400A3311C /* net_set.h */; };
-               1583EBA2108395BE00A3BC0C /* scutil.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A5405C0722B0099E85F /* scutil.c */; settings = {ATTRIBUTES = (); }; };
-               1583EBA3108395BE00A3BC0C /* commands.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A5605C0722B0099E85F /* commands.c */; settings = {ATTRIBUTES = (); }; };
-               1583EBA4108395BE00A3BC0C /* dictionary.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A5805C0722B0099E85F /* dictionary.c */; settings = {ATTRIBUTES = (); }; };
-               1583EBA5108395BE00A3BC0C /* session.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A5A05C0722B0099E85F /* session.c */; settings = {ATTRIBUTES = (); }; };
-               1583EBA6108395BE00A3BC0C /* cache.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A5C05C0722B0099E85F /* cache.c */; settings = {ATTRIBUTES = (); }; };
-               1583EBA7108395BE00A3BC0C /* notifications.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A5E05C0722B0099E85F /* notifications.c */; settings = {ATTRIBUTES = (); }; };
-               1583EBA8108395BE00A3BC0C /* tests.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A6005C0722B0099E85F /* tests.c */; settings = {ATTRIBUTES = (); }; };
-               1583EBA9108395BE00A3BC0C /* prefs.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A6205C0722B0099E85F /* prefs.c */; settings = {ATTRIBUTES = (); }; };
-               1583EBAA108395BE00A3BC0C /* net.c in Sources */ = {isa = PBXBuildFile; fileRef = 15A509A306C2518F001F0AB7 /* net.c */; };
-               1583EBAB108395BE00A3BC0C /* net_interface.c in Sources */ = {isa = PBXBuildFile; fileRef = 15DC34670711D49400A3311C /* net_interface.c */; };
-               1583EBAC108395BE00A3BC0C /* net_protocol.c in Sources */ = {isa = PBXBuildFile; fileRef = 15DC34690711D49400A3311C /* net_protocol.c */; };
-               1583EBAD108395BE00A3BC0C /* net_service.c in Sources */ = {isa = PBXBuildFile; fileRef = 15DC346B0711D49400A3311C /* net_service.c */; };
-               1583EBAE108395BE00A3BC0C /* net_set.c in Sources */ = {isa = PBXBuildFile; fileRef = 15DC346D0711D49400A3311C /* net_set.c */; };
-               1583EBB0108395BE00A3BC0C /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15CB6A6F05C0722B0099E85F /* CoreFoundation.framework */; };
-               1583EBB1108395BE00A3BC0C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1547072E0D1F70C80075C28D /* SystemConfiguration.framework */; };
-               1583EBB2108395BE00A3BC0C /* libedit.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 152CEED0070CF6640050F23C /* libedit.dylib */; };
                158E595E1107CAE40062081E /* helper.defs in Sources */ = {isa = PBXBuildFile; fileRef = 152E0E7E10FE820E00E402F2 /* helper.defs */; };
                158E595F1107CAE80062081E /* helper.defs in Sources */ = {isa = PBXBuildFile; fileRef = 152E0E7E10FE820E00E402F2 /* helper.defs */; };
-               158E59601107CAF10062081E /* helper.defs in Sources */ = {isa = PBXBuildFile; fileRef = 152E0E7E10FE820E00E402F2 /* helper.defs */; };
                158E59611107CAF40062081E /* helper.defs in Sources */ = {isa = PBXBuildFile; fileRef = 152E0E7E10FE820E00E402F2 /* helper.defs */; };
                15943D440E94081800B87535 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1543636A0752D03C00A8EC6C /* IOKit.framework */; };
+               1596A7B114EDB73D00798C39 /* libSystemConfiguration_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 1596A7AF14EDB73D00798C39 /* libSystemConfiguration_server.c */; };
+               1596A7B214EDB73D00798C39 /* libSystemConfiguration_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 1596A7AF14EDB73D00798C39 /* libSystemConfiguration_server.c */; };
+               1596A7B414EDB73D00798C39 /* libSystemConfiguration_server.h in Headers */ = {isa = PBXBuildFile; fileRef = 1596A7B014EDB73D00798C39 /* libSystemConfiguration_server.h */; };
+               1596A7B514EDB73D00798C39 /* libSystemConfiguration_server.h in Headers */ = {isa = PBXBuildFile; fileRef = 1596A7B014EDB73D00798C39 /* libSystemConfiguration_server.h */; };
                159A751A107FEAA400A57EAB /* VPNPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 159A7513107FEAA400A57EAB /* VPNPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
                159A751C107FEAA400A57EAB /* VPNConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 159A7515107FEAA400A57EAB /* VPNConfiguration.h */; settings = {ATTRIBUTES = (Private, ); }; };
                159A751E107FEAA400A57EAB /* VPNPrivate.c in Sources */ = {isa = PBXBuildFile; fileRef = 159A7517107FEAA400A57EAB /* VPNPrivate.c */; };
                159D54C407529FFF004F8947 /* _notifycancel.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A1405C0722B0099E85F /* _notifycancel.c */; settings = {ATTRIBUTES = (); }; };
                159D54C507529FFF004F8947 /* _snapshot.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A1605C0722B0099E85F /* _snapshot.c */; settings = {ATTRIBUTES = (); }; };
                159D54C607529FFF004F8947 /* config.defs in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69BE05C0722B0099E85F /* config.defs */; settings = {ATTRIBUTES = (Server, ); }; };
-               159D54C707529FFF004F8947 /* dnsinfo_private.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B73F0B05FD1B670096477F /* dnsinfo_private.c */; };
                159D54C807529FFF004F8947 /* dnsinfo_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B73F0D05FD1B670096477F /* dnsinfo_server.c */; };
-               159D54C907529FFF004F8947 /* shared_dns_info.defs in Sources */ = {isa = PBXBuildFile; fileRef = 15FCAAD005FD0EBF00CB79E6 /* shared_dns_info.defs */; settings = {ATTRIBUTES = (Server, ); }; };
                159D54CC07529FFF004F8947 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15CB6A6F05C0722B0099E85F /* CoreFoundation.framework */; };
                159D54CE07529FFF004F8947 /* libKernelEventMonitor.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 159D53D407528BDA004F8947 /* libKernelEventMonitor.a */; };
                159D54D007529FFF004F8947 /* libInterfaceNamer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 159D53E507528C4A004F8947 /* libInterfaceNamer.a */; };
                15A297300A13C08C009879B3 /* SCNetworkConnectionPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15A2972E0A13C08C009879B3 /* SCNetworkConnectionPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
                15A5A1E70D5B94190087BDA0 /* SCSchemaDefinitions.h in Headers */ = {isa = PBXBuildFile; fileRef = 150607DE075A00A300B147BA /* SCSchemaDefinitions.h */; settings = {ATTRIBUTES = (Public, ); }; };
                15A5A1E80D5B94190087BDA0 /* SystemConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB691305C0722B0099E85F /* SystemConfiguration.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
-               15A5A1E90D5B94190087BDA0 /* SCPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB691505C0722B0099E85F /* SCPrivate.h */; settings = {ATTRIBUTES = (Project, Private, ); }; };
+               15A5A1E90D5B94190087BDA0 /* SCPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB691505C0722B0099E85F /* SCPrivate.h */; settings = {ATTRIBUTES = (Private, Project, ); }; };
                15A5A1EA0D5B94190087BDA0 /* SCDPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB691705C0722B0099E85F /* SCDPlugin.h */; settings = {ATTRIBUTES = (Private, ); }; };
                15A5A1EB0D5B94190087BDA0 /* SCDynamicStoreInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB691B05C0722B0099E85F /* SCDynamicStoreInternal.h */; settings = {ATTRIBUTES = (Project, ); }; };
                15A5A1EC0D5B94190087BDA0 /* SCDynamicStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB691D05C0722B0099E85F /* SCDynamicStore.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
-               15A5A1ED0D5B94190087BDA0 /* SCDynamicStorePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB691F05C0722B0099E85F /* SCDynamicStorePrivate.h */; settings = {ATTRIBUTES = (Project, Private, ); }; };
+               15A5A1ED0D5B94190087BDA0 /* SCDynamicStorePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB691F05C0722B0099E85F /* SCDynamicStorePrivate.h */; settings = {ATTRIBUTES = (Private, Project, ); }; };
                15A5A1EE0D5B94190087BDA0 /* SCDynamicStoreKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692105C0722B0099E85F /* SCDynamicStoreKey.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
                15A5A1EF0D5B94190087BDA0 /* SCDynamicStoreCopySpecific.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692305C0722B0099E85F /* SCDynamicStoreCopySpecific.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
-               15A5A1F00D5B94190087BDA0 /* SCDynamicStoreCopySpecificPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692505C0722B0099E85F /* SCDynamicStoreCopySpecificPrivate.h */; settings = {ATTRIBUTES = (Project, Private, ); }; };
-               15A5A1F10D5B94190087BDA0 /* SCDynamicStoreSetSpecificPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692705C0722B0099E85F /* SCDynamicStoreSetSpecificPrivate.h */; settings = {ATTRIBUTES = (Project, Private, ); }; };
+               15A5A1F00D5B94190087BDA0 /* SCDynamicStoreCopySpecificPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692505C0722B0099E85F /* SCDynamicStoreCopySpecificPrivate.h */; settings = {ATTRIBUTES = (Private, Project, ); }; };
+               15A5A1F10D5B94190087BDA0 /* SCDynamicStoreSetSpecificPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692705C0722B0099E85F /* SCDynamicStoreSetSpecificPrivate.h */; settings = {ATTRIBUTES = (Private, Project, ); }; };
                15A5A1F20D5B94190087BDA0 /* SCPreferencesInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692905C0722B0099E85F /* SCPreferencesInternal.h */; settings = {ATTRIBUTES = (Project, ); }; };
                15A5A1F30D5B94190087BDA0 /* SCPreferences.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692B05C0722B0099E85F /* SCPreferences.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
-               15A5A1F40D5B94190087BDA0 /* SCPreferencesPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692D05C0722B0099E85F /* SCPreferencesPrivate.h */; settings = {ATTRIBUTES = (Project, Private, ); }; };
+               15A5A1F40D5B94190087BDA0 /* SCPreferencesPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692D05C0722B0099E85F /* SCPreferencesPrivate.h */; settings = {ATTRIBUTES = (Private, Project, ); }; };
                15A5A1F50D5B94190087BDA0 /* SCPreferencesPath.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692F05C0722B0099E85F /* SCPreferencesPath.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
                15A5A1F60D5B94190087BDA0 /* SCPreferencesSetSpecific.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB693105C0722B0099E85F /* SCPreferencesSetSpecific.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
                15A5A1F70D5B94190087BDA0 /* SCNetworkConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 15AD7A380670A85900BFE03C /* SCNetworkConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; };
                15A5A1F90D5B94190087BDA0 /* SCNetwork.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB693305C0722B0099E85F /* SCNetwork.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
                15A5A1FA0D5B94190087BDA0 /* SCNetworkConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB693505C0722B0099E85F /* SCNetworkConnection.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
                15A5A1FB0D5B94190087BDA0 /* SCNetworkReachability.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB693705C0722B0099E85F /* SCNetworkReachability.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
-               15A5A1FC0D5B94190087BDA0 /* SCValidation.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB693905C0722B0099E85F /* SCValidation.h */; settings = {ATTRIBUTES = (Project, Private, ); }; };
+               15A5A1FC0D5B94190087BDA0 /* SCValidation.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB693905C0722B0099E85F /* SCValidation.h */; settings = {ATTRIBUTES = (Private, Project, ); }; };
                15A5A1FD0D5B94190087BDA0 /* DHCPClientPreferences.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB693D05C0722B0099E85F /* DHCPClientPreferences.h */; settings = {ATTRIBUTES = (Public, ); }; };
                15A5A1FE0D5B94190087BDA0 /* SCDynamicStoreCopyDHCPInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB693F05C0722B0099E85F /* SCDynamicStoreCopyDHCPInfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
                15A5A1FF0D5B94190087BDA0 /* moh_msg.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB694105C0722B0099E85F /* moh_msg.h */; };
                15A5A2510D5B94190087BDA0 /* dy_framework.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69B405C0722B0099E85F /* dy_framework.c */; settings = {ATTRIBUTES = (); }; };
                15A5A2530D5B94190087BDA0 /* config.defs in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69BE05C0722B0099E85F /* config.defs */; settings = {ATTRIBUTES = (Client, ); }; };
                15A5A2540D5B94190087BDA0 /* SCPreferencesPathKey.c in Sources */ = {isa = PBXBuildFile; fileRef = 151BDA5D05D9E2ED00657BC7 /* SCPreferencesPathKey.c */; };
-               15A5A2550D5B94190087BDA0 /* dnsinfo_private.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B73F0B05FD1B670096477F /* dnsinfo_private.c */; };
-               15A5A2560D5B94190087BDA0 /* dnsinfo_copy.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B73F0805FD1B670096477F /* dnsinfo_copy.c */; };
-               15A5A2570D5B94190087BDA0 /* shared_dns_info.defs in Sources */ = {isa = PBXBuildFile; fileRef = 15FCAAD005FD0EBF00CB79E6 /* shared_dns_info.defs */; settings = {ATTRIBUTES = (Client, ); }; };
                15A5A2580D5B94190087BDA0 /* SCNetworkConfigurationInternal.c in Sources */ = {isa = PBXBuildFile; fileRef = 15AD7A390670A85900BFE03C /* SCNetworkConfigurationInternal.c */; };
                15A5A2590D5B94190087BDA0 /* SCNetworkInterface.c in Sources */ = {isa = PBXBuildFile; fileRef = 15AD7A3B0670A85900BFE03C /* SCNetworkInterface.c */; };
                15A5A25A0D5B94190087BDA0 /* SCNetworkProtocol.c in Sources */ = {isa = PBXBuildFile; fileRef = 15AD7A3C0670A85900BFE03C /* SCNetworkProtocol.c */; };
                15AAA7F7108E310700C2A607 /* VPNTunnelPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15AAA7F1108E310700C2A607 /* VPNTunnelPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
                15AAA7F8108E310700C2A607 /* VPNTunnel.h in Headers */ = {isa = PBXBuildFile; fileRef = 15AAA7F2108E310700C2A607 /* VPNTunnel.h */; settings = {ATTRIBUTES = (Private, ); }; };
                15AAA7F9108E310700C2A607 /* VPNTunnel.c in Sources */ = {isa = PBXBuildFile; fileRef = 15AAA7F3108E310700C2A607 /* VPNTunnel.c */; };
-               15B274A5114467CD003414AD /* nc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72B43727113C7BFC00EBF1B6 /* nc.c */; };
-               15B274A6114467D8003414AD /* nc.h in Headers */ = {isa = PBXBuildFile; fileRef = 72B43726113C7BFC00EBF1B6 /* nc.h */; };
+               15AB751516EBFF3400FAA8CE /* SCNetworkReachabilityServer_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 15C330BB134B92780028E36B /* SCNetworkReachabilityServer_server.c */; };
+               15AB752D16EC2AE900FAA8CE /* libIPMonitor_sim.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 15E1B05916EBAE3C00E5F06F /* libIPMonitor_sim.a */; };
+               15AB752E16EC2AE900FAA8CE /* libSCNetworkReachability_sim.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 15AB751916EBFF3400FAA8CE /* libSCNetworkReachability_sim.a */; };
                15BAA32307F0699A00D9EC95 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 15BAA32207F0699A00D9EC95 /* libbsm.dylib */; };
                15C330BC134B92780028E36B /* SCNetworkReachabilityServer_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 15C330B7134B92780028E36B /* SCNetworkReachabilityServer_client.c */; };
                15C330BD134B92780028E36B /* SCNetworkReachabilityServer_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 15C330B7134B92780028E36B /* SCNetworkReachabilityServer_client.c */; };
                15C330BE134B92780028E36B /* SCNetworkReachabilityServer_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 15C330B7134B92780028E36B /* SCNetworkReachabilityServer_client.c */; };
-               15C330BF134B92780028E36B /* SCNetworkReachabilityServer_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 15C330B7134B92780028E36B /* SCNetworkReachabilityServer_client.c */; };
-               15C330C0134B92780028E36B /* rb.c in Sources */ = {isa = PBXBuildFile; fileRef = 15C330B8134B92780028E36B /* rb.c */; };
-               15C330C1134B92780028E36B /* rb.c in Sources */ = {isa = PBXBuildFile; fileRef = 15C330B8134B92780028E36B /* rb.c */; };
-               15C330C2134B92780028E36B /* rb.c in Sources */ = {isa = PBXBuildFile; fileRef = 15C330B8134B92780028E36B /* rb.c */; };
-               15C330C3134B92780028E36B /* rb.c in Sources */ = {isa = PBXBuildFile; fileRef = 15C330B8134B92780028E36B /* rb.c */; };
-               15C330C4134B92780028E36B /* rb.h in Headers */ = {isa = PBXBuildFile; fileRef = 15C330B9134B92780028E36B /* rb.h */; };
-               15C330C5134B92780028E36B /* rb.h in Headers */ = {isa = PBXBuildFile; fileRef = 15C330B9134B92780028E36B /* rb.h */; };
-               15C330C6134B92780028E36B /* rb.h in Headers */ = {isa = PBXBuildFile; fileRef = 15C330B9134B92780028E36B /* rb.h */; };
-               15C330C7134B92780028E36B /* rb.h in Headers */ = {isa = PBXBuildFile; fileRef = 15C330B9134B92780028E36B /* rb.h */; };
                15C330D1134B95AA0028E36B /* SCNetworkReachabilityInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 15C330D0134B95AA0028E36B /* SCNetworkReachabilityInternal.h */; };
                15C330D2134B95AA0028E36B /* SCNetworkReachabilityInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 15C330D0134B95AA0028E36B /* SCNetworkReachabilityInternal.h */; };
                15C330D3134B95AA0028E36B /* SCNetworkReachabilityInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 15C330D0134B95AA0028E36B /* SCNetworkReachabilityInternal.h */; };
-               15C330D4134B95AA0028E36B /* SCNetworkReachabilityInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 15C330D0134B95AA0028E36B /* SCNetworkReachabilityInternal.h */; };
                15C330E5134BD2AC0028E36B /* SCNetworkReachabilityServer_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 15C330BB134B92780028E36B /* SCNetworkReachabilityServer_server.c */; };
-               15C330E6134BD2BB0028E36B /* SCNetworkReachabilityServer_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 15C330BB134B92780028E36B /* SCNetworkReachabilityServer_server.c */; };
+               15C8C6BF170AAB4E005375CE /* cache.c in Sources */ = {isa = PBXBuildFile; fileRef = 159D53CA07528B36004F8947 /* cache.c */; };
+               15C8C6C0170AAB4E005375CE /* cache.h in Headers */ = {isa = PBXBuildFile; fileRef = 159D53CB07528B36004F8947 /* cache.h */; };
+               15D2E437167643460078F547 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1520A3DE0846B2DC0010B584 /* Security.framework */; };
+               15D3083316F3EB0700014F82 /* libSimulatorSupport_sim.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 15D3082716F3E4DA00014F82 /* libSimulatorSupport_sim.a */; };
+               15D3083916F3EB8600014F82 /* simulator_support.c in Sources */ = {isa = PBXBuildFile; fileRef = 15D3083816F3EB8600014F82 /* simulator_support.c */; };
+               15D3083B16F4E81C00014F82 /* com.apple.configd_sim.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 15D3083A16F4E6D900014F82 /* com.apple.configd_sim.plist */; };
                15D48EBF0F67061600B4711E /* dnsinfo_create.c in Sources */ = {isa = PBXBuildFile; fileRef = 1521FC5C060F296A003B28F5 /* dnsinfo_create.c */; };
                15D48EC00F67061700B4711E /* dnsinfo_create.h in Headers */ = {isa = PBXBuildFile; fileRef = 1532629006281C9D00B1C10C /* dnsinfo_create.h */; };
                15D48EC10F67061F00B4711E /* dnsinfo_create.c in Sources */ = {isa = PBXBuildFile; fileRef = 1521FC5C060F296A003B28F5 /* dnsinfo_create.c */; };
                15D48EC20F67061F00B4711E /* dnsinfo_create.h in Headers */ = {isa = PBXBuildFile; fileRef = 1532629006281C9D00B1C10C /* dnsinfo_create.h */; };
-               15D48ED30F67079B00B4711E /* shared_dns_info.defs in Sources */ = {isa = PBXBuildFile; fileRef = 15FCAAD005FD0EBF00CB79E6 /* shared_dns_info.defs */; };
-               15D48ED40F6707A600B4711E /* shared_dns_info.defs in Sources */ = {isa = PBXBuildFile; fileRef = 15FCAAD005FD0EBF00CB79E6 /* shared_dns_info.defs */; };
+               15D54E2715B4FA4600F5229A /* com.apple.networking.IPMonitor in com.apple.networking.IPMonitor */ = {isa = PBXBuildFile; fileRef = D68AD25F159BCD5900D4F1BE /* com.apple.networking.IPMonitor */; };
+               15D54E2B15B4FB0300F5229A /* com.apple.networking.IPMonitor in com.apple.networking.IPMonitor */ = {isa = PBXBuildFile; fileRef = D68AD25F159BCD5900D4F1BE /* com.apple.networking.IPMonitor */; };
                15D8B22A1450D8450090CECF /* SCD.h in Headers */ = {isa = PBXBuildFile; fileRef = 15D8B2291450D8450090CECF /* SCD.h */; };
                15D8B22B1450D8450090CECF /* SCD.h in Headers */ = {isa = PBXBuildFile; fileRef = 15D8B2291450D8450090CECF /* SCD.h */; };
                15D8B22C1450D8450090CECF /* SCD.h in Headers */ = {isa = PBXBuildFile; fileRef = 15D8B2291450D8450090CECF /* SCD.h */; };
-               15D8B22D1450D8450090CECF /* SCD.h in Headers */ = {isa = PBXBuildFile; fileRef = 15D8B2291450D8450090CECF /* SCD.h */; };
-               15D9DCFB10DD90A1004E545D /* AppWorkaround.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 15D9DCFA10DD90A1004E545D /* AppWorkaround.plist */; };
+               15D9DCFB10DD90A1004E545D /* AppWorkaround.plist in AppWorkaround.plist */ = {isa = PBXBuildFile; fileRef = 15D9DCFA10DD90A1004E545D /* AppWorkaround.plist */; };
                15DAD5E1075913CE0084A6ED /* dnsinfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B73F0905FD1B670096477F /* dnsinfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
                15DAD5E2075913CE0084A6ED /* dnsinfo_private.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B73F0C05FD1B670096477F /* dnsinfo_private.h */; };
-               15DAD5E5075913CE0084A6ED /* shared_dns_info.defs in Sources */ = {isa = PBXBuildFile; fileRef = 15FCAAD005FD0EBF00CB79E6 /* shared_dns_info.defs */; settings = {ATTRIBUTES = (Client, ); }; };
                15DAD5E6075913CE0084A6ED /* dnsinfo_copy.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B73F0805FD1B670096477F /* dnsinfo_copy.c */; };
-               15DAD5E7075913CE0084A6ED /* dnsinfo_private.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B73F0B05FD1B670096477F /* dnsinfo_private.c */; };
                15DAD64307591A1A0084A6ED /* SystemConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB691305C0722B0099E85F /* SystemConfiguration.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
-               15DAD64407591A1A0084A6ED /* SCPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB691505C0722B0099E85F /* SCPrivate.h */; settings = {ATTRIBUTES = (Project, Private, ); }; };
+               15DAD64407591A1A0084A6ED /* SCPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB691505C0722B0099E85F /* SCPrivate.h */; settings = {ATTRIBUTES = (Private, Project, ); }; };
                15DAD64507591A1A0084A6ED /* SCDPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB691705C0722B0099E85F /* SCDPlugin.h */; settings = {ATTRIBUTES = (Private, ); }; };
                15DAD64607591A1A0084A6ED /* SCDynamicStoreInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB691B05C0722B0099E85F /* SCDynamicStoreInternal.h */; settings = {ATTRIBUTES = (Project, ); }; };
                15DAD64707591A1A0084A6ED /* SCDynamicStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB691D05C0722B0099E85F /* SCDynamicStore.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
-               15DAD64807591A1A0084A6ED /* SCDynamicStorePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB691F05C0722B0099E85F /* SCDynamicStorePrivate.h */; settings = {ATTRIBUTES = (Project, Private, ); }; };
+               15DAD64807591A1A0084A6ED /* SCDynamicStorePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB691F05C0722B0099E85F /* SCDynamicStorePrivate.h */; settings = {ATTRIBUTES = (Private, Project, ); }; };
                15DAD64907591A1A0084A6ED /* SCDynamicStoreKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692105C0722B0099E85F /* SCDynamicStoreKey.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
                15DAD64A07591A1A0084A6ED /* SCDynamicStoreCopySpecific.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692305C0722B0099E85F /* SCDynamicStoreCopySpecific.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
-               15DAD64B07591A1A0084A6ED /* SCDynamicStoreCopySpecificPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692505C0722B0099E85F /* SCDynamicStoreCopySpecificPrivate.h */; settings = {ATTRIBUTES = (Project, Private, ); }; };
-               15DAD64C07591A1A0084A6ED /* SCDynamicStoreSetSpecificPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692705C0722B0099E85F /* SCDynamicStoreSetSpecificPrivate.h */; settings = {ATTRIBUTES = (Project, Private, ); }; };
+               15DAD64B07591A1A0084A6ED /* SCDynamicStoreCopySpecificPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692505C0722B0099E85F /* SCDynamicStoreCopySpecificPrivate.h */; settings = {ATTRIBUTES = (Private, Project, ); }; };
+               15DAD64C07591A1A0084A6ED /* SCDynamicStoreSetSpecificPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692705C0722B0099E85F /* SCDynamicStoreSetSpecificPrivate.h */; settings = {ATTRIBUTES = (Private, Project, ); }; };
                15DAD64D07591A1A0084A6ED /* SCPreferencesInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692905C0722B0099E85F /* SCPreferencesInternal.h */; settings = {ATTRIBUTES = (Project, ); }; };
                15DAD64E07591A1A0084A6ED /* SCPreferences.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692B05C0722B0099E85F /* SCPreferences.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
-               15DAD64F07591A1A0084A6ED /* SCPreferencesPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692D05C0722B0099E85F /* SCPreferencesPrivate.h */; settings = {ATTRIBUTES = (Project, Private, ); }; };
+               15DAD64F07591A1A0084A6ED /* SCPreferencesPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692D05C0722B0099E85F /* SCPreferencesPrivate.h */; settings = {ATTRIBUTES = (Private, Project, ); }; };
                15DAD65007591A1A0084A6ED /* SCPreferencesPath.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB692F05C0722B0099E85F /* SCPreferencesPath.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
                15DAD65107591A1A0084A6ED /* SCPreferencesSetSpecific.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB693105C0722B0099E85F /* SCPreferencesSetSpecific.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
                15DAD65207591A1A0084A6ED /* SCNetworkConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 15AD7A380670A85900BFE03C /* SCNetworkConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; };
                15DAD65407591A1A0084A6ED /* SCNetwork.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB693305C0722B0099E85F /* SCNetwork.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
                15DAD65507591A1A0084A6ED /* SCNetworkConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB693505C0722B0099E85F /* SCNetworkConnection.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
                15DAD65607591A1A0084A6ED /* SCNetworkReachability.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB693705C0722B0099E85F /* SCNetworkReachability.h */; settings = {ATTRIBUTES = (Public, Project, ); }; };
-               15DAD65707591A1A0084A6ED /* SCValidation.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB693905C0722B0099E85F /* SCValidation.h */; settings = {ATTRIBUTES = (Project, Private, ); }; };
+               15DAD65707591A1A0084A6ED /* SCValidation.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB693905C0722B0099E85F /* SCValidation.h */; settings = {ATTRIBUTES = (Private, Project, ); }; };
                15DAD65807591A1A0084A6ED /* DHCPClientPreferences.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB693D05C0722B0099E85F /* DHCPClientPreferences.h */; settings = {ATTRIBUTES = (Public, ); }; };
                15DAD65907591A1A0084A6ED /* SCDynamicStoreCopyDHCPInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB693F05C0722B0099E85F /* SCDynamicStoreCopyDHCPInfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
                15DAD65A07591A1A0084A6ED /* moh_msg.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB694105C0722B0099E85F /* moh_msg.h */; };
                15DAD65B07591A1A0084A6ED /* moh.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB694305C0722B0099E85F /* moh.h */; };
                15DAD65C07591A1A0084A6ED /* DeviceOnHold.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB694505C0722B0099E85F /* DeviceOnHold.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               15DAD65D07591A1A0084A6ED /* LinkConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB694705C0722B0099E85F /* LinkConfiguration.h */; settings = {ATTRIBUTES = (Private, ); }; };
                15DAD65E07591A1A0084A6ED /* dy_framework.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB694905C0722B0099E85F /* dy_framework.h */; };
                15DAD66107591A1A0084A6ED /* SCPreferencesPathKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 151BDA2B05D9E28B00657BC7 /* SCPreferencesPathKey.h */; settings = {ATTRIBUTES = (Private, ); }; };
                15DAD66407591A1A0084A6ED /* pppcontroller_types.h in Headers */ = {isa = PBXBuildFile; fileRef = 23C1E2B4062DD2C700835B54 /* pppcontroller_types.h */; };
                15DAD69F07591A1A0084A6ED /* VLANConfiguration.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69B605C0722B0099E85F /* VLANConfiguration.c */; settings = {ATTRIBUTES = (); COMPILER_FLAGS = "-Wno-deprecated-declarations"; }; };
                15DAD6A007591A1A0084A6ED /* config.defs in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69BE05C0722B0099E85F /* config.defs */; settings = {ATTRIBUTES = (Client, ); }; };
                15DAD6A207591A1A0084A6ED /* SCPreferencesPathKey.c in Sources */ = {isa = PBXBuildFile; fileRef = 151BDA5D05D9E2ED00657BC7 /* SCPreferencesPathKey.c */; };
-               15DAD6A507591A1A0084A6ED /* shared_dns_info.defs in Sources */ = {isa = PBXBuildFile; fileRef = 15FCAAD005FD0EBF00CB79E6 /* shared_dns_info.defs */; settings = {ATTRIBUTES = (Client, ); }; };
                15DAD6A607591A1A0084A6ED /* SCNetworkConfigurationInternal.c in Sources */ = {isa = PBXBuildFile; fileRef = 15AD7A390670A85900BFE03C /* SCNetworkConfigurationInternal.c */; };
                15DAD6A707591A1A0084A6ED /* SCNetworkInterface.c in Sources */ = {isa = PBXBuildFile; fileRef = 15AD7A3B0670A85900BFE03C /* SCNetworkInterface.c */; settings = {COMPILER_FLAGS = "-Wno-deprecated-declarations"; }; };
                15DAD6A807591A1A0084A6ED /* SCNetworkProtocol.c in Sources */ = {isa = PBXBuildFile; fileRef = 15AD7A3C0670A85900BFE03C /* SCNetworkProtocol.c */; settings = {COMPILER_FLAGS = "-Wno-deprecated-declarations"; }; };
                15DAD6AE07591A1A0084A6ED /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15CB6A6F05C0722B0099E85F /* CoreFoundation.framework */; };
                15DAF2DC08466D4900D1B2BD /* SCHelper_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 15DAF2D808466D4900D1B2BD /* SCHelper_client.c */; };
                15DAF2E108466D4900D1B2BD /* SCHelper_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 15DAF2D908466D4900D1B2BD /* SCHelper_server.c */; };
+               15E1B04316EBAE3C00E5F06F /* dns-configuration.h in Headers */ = {isa = PBXBuildFile; fileRef = 155D22380AF13A7300D52ED0 /* dns-configuration.h */; };
+               15E1B04416EBAE3C00E5F06F /* dnsinfo_create.h in Headers */ = {isa = PBXBuildFile; fileRef = 1532629006281C9D00B1C10C /* dnsinfo_create.h */; };
+               15E1B04516EBAE3C00E5F06F /* network_information_priv.h in Headers */ = {isa = PBXBuildFile; fileRef = D6986A761368911E0091C931 /* network_information_priv.h */; };
+               15E1B04616EBAE3C00E5F06F /* proxy-configuration.h in Headers */ = {isa = PBXBuildFile; fileRef = 1575FD2612CD15C60003D86E /* proxy-configuration.h */; };
+               15E1B04816EBAE3C00E5F06F /* network_information_server.h in Headers */ = {isa = PBXBuildFile; fileRef = 153ACCA714E322D5005029A5 /* network_information_server.h */; };
+               15E1B04916EBAE3C00E5F06F /* libSystemConfiguration_server.h in Headers */ = {isa = PBXBuildFile; fileRef = 1596A7B014EDB73D00798C39 /* libSystemConfiguration_server.h */; };
+               15E1B04B16EBAE3C00E5F06F /* dns-configuration.c in Sources */ = {isa = PBXBuildFile; fileRef = 159D53AA07528B36004F8947 /* dns-configuration.c */; };
+               15E1B04C16EBAE3C00E5F06F /* dnsinfo_create.c in Sources */ = {isa = PBXBuildFile; fileRef = 1521FC5C060F296A003B28F5 /* dnsinfo_create.c */; };
+               15E1B04D16EBAE3C00E5F06F /* dnsinfo_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B73F0D05FD1B670096477F /* dnsinfo_server.c */; };
+               15E1B04E16EBAE3C00E5F06F /* ip_plugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 159D53A707528B36004F8947 /* ip_plugin.c */; };
+               15E1B04F16EBAE3C00E5F06F /* network_information_priv.c in Sources */ = {isa = PBXBuildFile; fileRef = D6986A75136891120091C931 /* network_information_priv.c */; };
+               15E1B05016EBAE3C00E5F06F /* network_information_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 153ACCA614E322D5005029A5 /* network_information_server.c */; };
+               15E1B05116EBAE3C00E5F06F /* proxy-configuration.c in Sources */ = {isa = PBXBuildFile; fileRef = 1575FD2512CD15C60003D86E /* proxy-configuration.c */; };
+               15E1B05316EBAE3C00E5F06F /* libSystemConfiguration_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 1596A7AF14EDB73D00798C39 /* libSystemConfiguration_server.c */; };
+               15E1B05416EBAE3C00E5F06F /* scprefs_observer.c in Sources */ = {isa = PBXBuildFile; fileRef = D61AAEAD1522C99C0066B003 /* scprefs_observer.c */; };
+               15E1B05516EBAE3C00E5F06F /* IPMonitorControlPrefs.c in Sources */ = {isa = PBXBuildFile; fileRef = F9A3780E16A4846E00C57CDC /* IPMonitorControlPrefs.c */; };
                15F21618110F823500E89CF7 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 15BAA32207F0699A00D9EC95 /* libbsm.dylib */; };
-               15F21619110F826800E89CF7 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 15BAA32207F0699A00D9EC95 /* libbsm.dylib */; };
                15FC130B0CCEA59E0013872C /* monitor.c in Sources */ = {isa = PBXBuildFile; fileRef = 15FC130A0CCEA59E0013872C /* monitor.c */; };
                15FC13180CCF74740013872C /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15CB6A6F05C0722B0099E85F /* CoreFoundation.framework */; };
                15FD7B3C101E439200C56621 /* BridgeConfiguration.c in Sources */ = {isa = PBXBuildFile; fileRef = 15FD7B3B101E439200C56621 /* BridgeConfiguration.c */; };
                72B43729113C7BFC00EBF1B6 /* nc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72B43727113C7BFC00EBF1B6 /* nc.c */; };
                72B4372A113C7BFC00EBF1B6 /* nc.h in Headers */ = {isa = PBXBuildFile; fileRef = 72B43726113C7BFC00EBF1B6 /* nc.h */; };
                72B4372B113C7BFC00EBF1B6 /* nc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72B43727113C7BFC00EBF1B6 /* nc.c */; };
+               72C3E82715003E78000D68CB /* MobileInstallation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72C3E82615003E78000D68CB /* MobileInstallation.framework */; };
+               B03FEFB616376D2800A1B88F /* VPNAppLayer.c in Sources */ = {isa = PBXBuildFile; fileRef = B03FEFB516376D2800A1B88F /* VPNAppLayer.c */; };
+               B03FEFB716376D2800A1B88F /* VPNAppLayer.c in Sources */ = {isa = PBXBuildFile; fileRef = B03FEFB516376D2800A1B88F /* VPNAppLayer.c */; };
+               B03FEFBA16382C0700A1B88F /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 15BAA32207F0699A00D9EC95 /* libbsm.dylib */; };
+               B03FEFBB16382C1300A1B88F /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 15BAA32207F0699A00D9EC95 /* libbsm.dylib */; };
+               B084710F16385121006C92A3 /* SCNetworkConnectionInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = B084710E16385121006C92A3 /* SCNetworkConnectionInternal.h */; };
+               B084711016385121006C92A3 /* SCNetworkConnectionInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = B084710E16385121006C92A3 /* SCNetworkConnectionInternal.h */; };
+               B0A88CA716397A1200A60B3A /* VPNAppLayerPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = B0A88CA616397A1200A60B3A /* VPNAppLayerPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               B0A88CA816397A1200A60B3A /* VPNAppLayerPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = B0A88CA616397A1200A60B3A /* VPNAppLayerPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               B0C967F817441F0E00889853 /* SNHelperPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = B0C967F717441F0E00889853 /* SNHelperPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               B0C9689C174426C600889853 /* SNHelper.c in Sources */ = {isa = PBXBuildFile; fileRef = B0C9689B174426C200889853 /* SNHelper.c */; };
+               B0C9689D174426D100889853 /* SNHelper.c in Sources */ = {isa = PBXBuildFile; fileRef = B0C9689B174426C200889853 /* SNHelper.c */; };
+               B0C9689E174426DD00889853 /* SNHelperPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = B0C967F717441F0E00889853 /* SNHelperPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               B0FEF41A164406F400174B99 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 15BAA32207F0699A00D9EC95 /* libbsm.dylib */; };
+               B0FEF41B1644089200174B99 /* VPNAppLayer.c in Sources */ = {isa = PBXBuildFile; fileRef = B03FEFB516376D2800A1B88F /* VPNAppLayer.c */; };
+               C4CDB8151631935700819B44 /* VPNFlow.c in Sources */ = {isa = PBXBuildFile; fileRef = C4CDB8141631935700819B44 /* VPNFlow.c */; };
+               C4CDB8161631935700819B44 /* VPNFlow.c in Sources */ = {isa = PBXBuildFile; fileRef = C4CDB8141631935700819B44 /* VPNFlow.c */; };
+               C4CDB8171631938000819B44 /* VPNFlow.h in Headers */ = {isa = PBXBuildFile; fileRef = C4CDB8111631933400819B44 /* VPNFlow.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               C4CDB8181631938400819B44 /* VPNFlowPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = C4CDB8121631933400819B44 /* VPNFlowPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               C4CDB819163193AA00819B44 /* VPNFlow.h in Headers */ = {isa = PBXBuildFile; fileRef = C4CDB8111631933400819B44 /* VPNFlow.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               C4CDB81A163193AF00819B44 /* VPNFlowPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = C4CDB8121631933400819B44 /* VPNFlowPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               C4F1848016237AFC00D97043 /* VPNService.c in Sources */ = {isa = PBXBuildFile; fileRef = C4F1847F16237AFC00D97043 /* VPNService.c */; };
+               C4F1848116237AFC00D97043 /* VPNService.c in Sources */ = {isa = PBXBuildFile; fileRef = C4F1847F16237AFC00D97043 /* VPNService.c */; };
+               C4F1848316237B1400D97043 /* VPNService.c in Sources */ = {isa = PBXBuildFile; fileRef = C4F1847F16237AFC00D97043 /* VPNService.c */; };
+               D61AAEAE1522C99C0066B003 /* scprefs_observer.c in Sources */ = {isa = PBXBuildFile; fileRef = D61AAEAD1522C99C0066B003 /* scprefs_observer.c */; };
+               D61AAEAF1522C99C0066B003 /* scprefs_observer.c in Sources */ = {isa = PBXBuildFile; fileRef = D61AAEAD1522C99C0066B003 /* scprefs_observer.c */; };
+               D61AAEB01522C99C0066B003 /* scprefs_observer.c in Sources */ = {isa = PBXBuildFile; fileRef = D61AAEAD1522C99C0066B003 /* scprefs_observer.c */; };
+               D61AAEB11522C99C0066B003 /* scprefs_observer.c in Sources */ = {isa = PBXBuildFile; fileRef = D61AAEAD1522C99C0066B003 /* scprefs_observer.c */; };
+               D61AAEB21522C99C0066B003 /* scprefs_observer.c in Sources */ = {isa = PBXBuildFile; fileRef = D61AAEAD1522C99C0066B003 /* scprefs_observer.c */; };
+               D61AAEB51522C9D00066B003 /* scprefs_observer.h in Headers */ = {isa = PBXBuildFile; fileRef = D61AAEB41522C9BD0066B003 /* scprefs_observer.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               D61AAEB61522C9E60066B003 /* scprefs_observer.h in Headers */ = {isa = PBXBuildFile; fileRef = D61AAEB41522C9BD0066B003 /* scprefs_observer.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               D61AAEB71522C9EF0066B003 /* scprefs_observer.h in Headers */ = {isa = PBXBuildFile; fileRef = D61AAEB41522C9BD0066B003 /* scprefs_observer.h */; settings = {ATTRIBUTES = (Private, ); }; };
                D661C2EF1368BB280030B977 /* network_information.h in Headers */ = {isa = PBXBuildFile; fileRef = D6986A781368913C0091C931 /* network_information.h */; settings = {ATTRIBUTES = (Public, ); }; };
                D661C2F11368BB600030B977 /* network_information.c in Sources */ = {isa = PBXBuildFile; fileRef = D6986A77136891300091C931 /* network_information.c */; };
                D661C2F21368BB720030B977 /* network_information.h in Headers */ = {isa = PBXBuildFile; fileRef = D6986A781368913C0091C931 /* network_information.h */; settings = {ATTRIBUTES = (Public, ); }; };
                E49173E1137C4E4F0000089F /* network_information_priv.c in Sources */ = {isa = PBXBuildFile; fileRef = D6986A75136891120091C931 /* network_information_priv.c */; };
                E4F211D3137B0AB900BBB915 /* network_information_priv.c in Sources */ = {isa = PBXBuildFile; fileRef = D6986A75136891120091C931 /* network_information_priv.c */; };
                E4F211D4137B0ABD00BBB915 /* network_information_priv.h in Headers */ = {isa = PBXBuildFile; fileRef = D6986A761368911E0091C931 /* network_information_priv.h */; };
-               E4F211D5137B0AD700BBB915 /* network_information_priv.c in Sources */ = {isa = PBXBuildFile; fileRef = D6986A75136891120091C931 /* network_information_priv.c */; };
-               E4F211D6137B0ADB00BBB915 /* network_information_priv.h in Headers */ = {isa = PBXBuildFile; fileRef = D6986A761368911E0091C931 /* network_information_priv.h */; };
                E4F211D7137B0AF200BBB915 /* network_information_priv.h in Headers */ = {isa = PBXBuildFile; fileRef = D6986A761368911E0091C931 /* network_information_priv.h */; };
                F95B8A430B03E07A00993BA3 /* SCNetworkSignature.c in Sources */ = {isa = PBXBuildFile; fileRef = F95B8A420B03E07A00993BA3 /* SCNetworkSignature.c */; };
                F95B8A460B03E09300993BA3 /* SCNetworkSignature.h in Headers */ = {isa = PBXBuildFile; fileRef = F95B8A440B03E09300993BA3 /* SCNetworkSignature.h */; settings = {ATTRIBUTES = (Private, ); }; };
                F95B8A470B03E09300993BA3 /* SCNetworkSignaturePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = F95B8A450B03E09300993BA3 /* SCNetworkSignaturePrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               F9A3781016A4847700C57CDC /* IPMonitorControlPrefs.c in Sources */ = {isa = PBXBuildFile; fileRef = F9A3780E16A4846E00C57CDC /* IPMonitorControlPrefs.c */; };
+               F9A3781116A4849100C57CDC /* IPMonitorControlPrefs.c in Sources */ = {isa = PBXBuildFile; fileRef = F9A3780E16A4846E00C57CDC /* IPMonitorControlPrefs.c */; };
+               F9B50FF316A4CBB200CA274E /* IPMonitorControlPrefs.c in Sources */ = {isa = PBXBuildFile; fileRef = F9A3780E16A4846E00C57CDC /* IPMonitorControlPrefs.c */; };
+               F9B50FF416A4CBB800CA274E /* IPMonitorControlPrefs.c in Sources */ = {isa = PBXBuildFile; fileRef = F9A3780E16A4846E00C57CDC /* IPMonitorControlPrefs.c */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
                        remoteGlobalIDString = 1528BFF813573FF500691881;
                        remoteInfo = "SCNetworkReachability.bundle-Embedded";
                };
-               1528C0121357420300691881 /* PBXContainerItemProxy */ = {
-                       isa = PBXContainerItemProxy;
-                       containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
-                       proxyType = 1;
-                       remoteGlobalIDString = 1528BFFF1357401900691881;
-                       remoteInfo = "SCNetworkReachability-EmbeddedOther";
-               };
-               1528C0141357420300691881 /* PBXContainerItemProxy */ = {
-                       isa = PBXContainerItemProxy;
-                       containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
-                       proxyType = 1;
-                       remoteGlobalIDString = 1528C0071357401D00691881;
-                       remoteInfo = "SCNetworkReachability.bundle-EmbeddedOther";
-               };
                1558480507550D470046C2E9 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
                        remoteGlobalIDString = 156CA4790EF853BB00C59A18;
                        remoteInfo = "Logger.bundle-Embedded";
                };
+               15732AE516EA6BCE00F3AC4C /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = 15732AD616EA6B6700F3AC4C;
+                       remoteInfo = "libsystem_configuration-EmbeddedSimulator";
+               };
                1574341E0D4A815E002ACA73 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
                        remoteGlobalIDString = 157BB8AE075924360025DA7A;
                        remoteInfo = Frameworks;
                };
+               157FDE43164A079B0040D6A8 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = 157FDE3B164A075F0040D6A8;
+                       remoteInfo = "configd_libSystem-EmbeddedSimulator";
+               };
                15828B060753B77E00AD4710 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
                        remoteGlobalIDString = 15A5A1E40D5B94190087BDA0;
                        remoteInfo = "SystemConfiguration.framework-EmbeddedSimulator";
                };
-               15AC515710839608004A9ED5 /* PBXContainerItemProxy */ = {
-                       isa = PBXContainerItemProxy;
-                       containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
-                       proxyType = 1;
-                       remoteGlobalIDString = 1583E9FD108395BB00A3BC0C;
-                       remoteInfo = "configd_libSystem-EmbeddedOther";
-               };
-               15AC515A1083960E004A9ED5 /* PBXContainerItemProxy */ = {
-                       isa = PBXContainerItemProxy;
-                       containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
-                       proxyType = 1;
-                       remoteGlobalIDString = 1583EA11108395BB00A3BC0C;
-                       remoteInfo = "configd_base-EmbeddedOther";
-               };
-               15AC515C10839613004A9ED5 /* PBXContainerItemProxy */ = {
-                       isa = PBXContainerItemProxy;
-                       containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
-                       proxyType = 1;
-                       remoteGlobalIDString = 1583EAAC108395BB00A3BC0C;
-                       remoteInfo = "configd_plugins-EmbeddedOther";
-               };
-               15AC515E1083961E004A9ED5 /* PBXContainerItemProxy */ = {
-                       isa = PBXContainerItemProxy;
-                       containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
-                       proxyType = 1;
-                       remoteGlobalIDString = 1583EB41108395BD00A3BC0C;
-                       remoteInfo = "configd_executables-EmbeddedOther";
-               };
-               15AC516010839649004A9ED5 /* PBXContainerItemProxy */ = {
-                       isa = PBXContainerItemProxy;
-                       containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
-                       proxyType = 1;
-                       remoteGlobalIDString = 1583EA04108395BB00A3BC0C;
-                       remoteInfo = "DNSConfiguration-EmbeddedOther";
-               };
-               15AC516210839666004A9ED5 /* PBXContainerItemProxy */ = {
-                       isa = PBXContainerItemProxy;
-                       containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
-                       proxyType = 1;
-                       remoteGlobalIDString = 1583EA19108395BB00A3BC0C;
-                       remoteInfo = "SystemConfiguration.framework-EmbeddedOther";
-               };
-               15AC51641083966B004A9ED5 /* PBXContainerItemProxy */ = {
-                       isa = PBXContainerItemProxy;
-                       containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
-                       proxyType = 1;
-                       remoteGlobalIDString = 1583EA9B108395BB00A3BC0C;
-                       remoteInfo = "SCHelper-EmbeddedOther";
-               };
-               15AC5169108396B7004A9ED5 /* PBXContainerItemProxy */ = {
+               15AB752116EC005A00FAA8CE /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = 1583EB92108395BE00A3BC0C;
-                       remoteInfo = "scutil-EmbeddedOther";
+                       remoteGlobalIDString = 15AB751216EBFF3400FAA8CE;
+                       remoteInfo = "SCNetworkReachability-EmbeddedSimulator";
                };
-               15AC516B108396B7004A9ED5 /* PBXContainerItemProxy */ = {
+               15AB752316EC005A00FAA8CE /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = 1583EB86108395BE00A3BC0C;
-                       remoteInfo = "scselect-EmbeddedOther";
+                       remoteGlobalIDString = 15AB751A16EBFF8A00FAA8CE;
+                       remoteInfo = "SCNetworkReachability.bundle-EmbeddedSimulator";
                };
-               15AC516D108396B7004A9ED5 /* PBXContainerItemProxy */ = {
+               15AB752916EC254D00FAA8CE /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = 1583EB4B108395BD00A3BC0C;
-                       remoteInfo = "configd-EmbeddedOther";
+                       remoteGlobalIDString = 15E1B04116EBAE3C00E5F06F;
+                       remoteInfo = "IPMonitor-EmbeddedSimulator";
                };
-               15AC5170108396D2004A9ED5 /* PBXContainerItemProxy */ = {
+               15AB752B16EC254D00FAA8CE /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = 1583EB3A108395BD00A3BC0C;
-                       remoteInfo = "PreferencesMonitor.bundle-EmbeddedOther";
+                       remoteGlobalIDString = 15AB751216EBFF3400FAA8CE;
+                       remoteInfo = "SCNetworkReachability-EmbeddedSimulator";
                };
-               15AC5172108396D2004A9ED5 /* PBXContainerItemProxy */ = {
+               15C64A210F684C4900D78394 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = 1583EB32108395BD00A3BC0C;
-                       remoteInfo = "PreferencesMonitor-EmbeddedOther";
+                       remoteGlobalIDString = 15DAD5DF075913CE0084A6ED;
+                       remoteInfo = DNSConfiguration;
                };
-               15AC5178108396D2004A9ED5 /* PBXContainerItemProxy */ = {
+               15C64A230F684C5700D78394 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = 1583EB16108395BC00A3BC0C;
-                       remoteInfo = "Logger.bundle-EmbeddedOther";
+                       remoteGlobalIDString = 15C64A1E0F684C3300D78394;
+                       remoteInfo = configd_libSystem;
                };
-               15AC517A108396D2004A9ED5 /* PBXContainerItemProxy */ = {
+               15C64A2E0F684C8300D78394 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = 1583EB0F108395BC00A3BC0C;
-                       remoteInfo = "LinkConfiguration.bundle-EmbeddedOther";
+                       remoteGlobalIDString = 15C64A280F684C6B00D78394;
+                       remoteInfo = "configd_libSystem-Embedded";
                };
-               15AC517C108396D2004A9ED5 /* PBXContainerItemProxy */ = {
+               15C64A300F684C8F00D78394 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = 1583EB07108395BC00A3BC0C;
-                       remoteInfo = "LinkConfiguration-EmbeddedOther";
+                       remoteGlobalIDString = 157A84D80D56C63900B6F1A0;
+                       remoteInfo = "DNSConfiguration-Embedded";
                };
-               15AC517E108396D2004A9ED5 /* PBXContainerItemProxy */ = {
+               15D3082F16F3EAD000014F82 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = 1583EB00108395BC00A3BC0C;
-                       remoteInfo = "KernelEventMonitor.bundle-EmbeddedOther";
+                       remoteGlobalIDString = 15D3080F16F3E4DA00014F82;
+                       remoteInfo = "SimulatorSupport-EmbeddedSimulator";
                };
-               15AC5180108396D2004A9ED5 /* PBXContainerItemProxy */ = {
+               15D3083116F3EAD000014F82 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = 1583EAEF108395BC00A3BC0C;
-                       remoteInfo = "KernelEventMonitor-EmbeddedOther";
+                       remoteGlobalIDString = 15D3082816F3E4E100014F82;
+                       remoteInfo = "SimulatorSupport.bundle-EmbeddedSimulator";
                };
-               15AC5182108396D2004A9ED5 /* PBXContainerItemProxy */ = {
+               15D3083416F3EB2500014F82 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = 1583EAE8108395BC00A3BC0C;
-                       remoteInfo = "InterfaceNamer.bundle-EmbeddedOther";
+                       remoteGlobalIDString = 15D3080F16F3E4DA00014F82;
+                       remoteInfo = "SimulatorSupport-EmbeddedSimulator";
                };
-               15AC5184108396D2004A9ED5 /* PBXContainerItemProxy */ = {
+               15E1B03D16EBAB8A00E5F06F /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = 1583EAE0108395BB00A3BC0C;
-                       remoteInfo = "InterfaceNamer-EmbeddedOther";
+                       remoteGlobalIDString = 15732A7616EA503200F3AC4C;
+                       remoteInfo = "configd-EmbeddedSimulator";
                };
-               15AC5186108396D2004A9ED5 /* PBXContainerItemProxy */ = {
+               15E1B03F16EBAB9400E5F06F /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = 1583EAD9108395BB00A3BC0C;
-                       remoteInfo = "IPMonitor.bundle-EmbeddedOther";
+                       remoteGlobalIDString = 15732AAD16EA511900F3AC4C;
+                       remoteInfo = "scutil-EmbeddedSimulator";
                };
-               15AC5188108396D2004A9ED5 /* PBXContainerItemProxy */ = {
+               15E1B06316EBAF2A00E5F06F /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = 1583EACA108395BB00A3BC0C;
-                       remoteInfo = "IPMonitor-EmbeddedOther";
+                       remoteGlobalIDString = 15E1B04116EBAE3C00E5F06F;
+                       remoteInfo = "IPMonitor-EmbeddedSimulator";
                };
-               15C64A210F684C4900D78394 /* PBXContainerItemProxy */ = {
+               15E1B06516EBAF2A00E5F06F /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = 15DAD5DF075913CE0084A6ED;
-                       remoteInfo = DNSConfiguration;
+                       remoteGlobalIDString = 15E1B05A16EBAE7800E5F06F;
+                       remoteInfo = "IPMonitor.bundle-EmbeddedSimulator";
                };
-               15C64A230F684C5700D78394 /* PBXContainerItemProxy */ = {
+               15E83108167F9B0600FD51EC /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = 15C64A1E0F684C3300D78394;
-                       remoteInfo = configd_libSystem;
+                       remoteGlobalIDString = 15CB690005C0722A0099E85F;
+                       remoteInfo = All;
                };
-               15C64A2E0F684C8300D78394 /* PBXContainerItemProxy */ = {
+               15E8310A167F9B0C00FD51EC /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = 15C64A280F684C6B00D78394;
-                       remoteInfo = "configd_libSystem-Embedded";
+                       remoteGlobalIDString = 151C1CC60CFB487000C5AFD6;
+                       remoteInfo = "All-Embedded";
                };
-               15C64A300F684C8F00D78394 /* PBXContainerItemProxy */ = {
+               15E8310C167F9B1200FD51EC /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = 157A84D80D56C63900B6F1A0;
-                       remoteInfo = "DNSConfiguration-Embedded";
+                       remoteGlobalIDString = 15FD13BF0D59485000F9409C;
+                       remoteInfo = "All-EmbeddedSimulator";
                };
                D6DDAC3C147A24BC00A2E902 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        );
                        runOnlyForDeploymentPostprocessing = 1;
                };
+               15732AA716EA503200F3AC4C /* CopyFiles */ = {
+                       isa = PBXCopyFilesBuildPhase;
+                       buildActionMask = 8;
+                       dstPath = "$(SDKROOT)/System/Library/LaunchDaemons";
+                       dstSubfolderSpec = 0;
+                       files = (
+                               15D3083B16F4E81C00014F82 /* com.apple.configd_sim.plist in CopyFiles */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 1;
+               };
                1583175B0CFB80A1006F62B9 /* CopyFiles */ = {
                        isa = PBXCopyFilesBuildPhase;
                        buildActionMask = 8;
                        );
                        runOnlyForDeploymentPostprocessing = 1;
                };
-               1583EAA5108395BB00A3BC0C /* CopyFiles */ = {
+               159D54D507529FFF004F8947 /* CopyFiles */ = {
                        isa = PBXCopyFilesBuildPhase;
                        buildActionMask = 8;
-                       dstPath = /System/Library/LaunchDaemons;
+                       dstPath = /usr/share/man/man8;
                        dstSubfolderSpec = 0;
                        files = (
-                               1583EAA6108395BB00A3BC0C /* com.apple.SCHelper-embedded.plist in CopyFiles */,
+                               159D54D607529FFF004F8947 /* configd.8 in CopyFiles */,
                        );
                        runOnlyForDeploymentPostprocessing = 1;
                };
-               1583EB7F108395BD00A3BC0C /* CopyFiles */ = {
+               159D54D707529FFF004F8947 /* CopyFiles */ = {
                        isa = PBXCopyFilesBuildPhase;
                        buildActionMask = 8;
                        dstPath = /System/Library/LaunchDaemons;
                        dstSubfolderSpec = 0;
                        files = (
-                               1583EB80108395BD00A3BC0C /* com.apple.configd.plist in CopyFiles */,
+                               1540E3610987DA9500157C07 /* com.apple.configd.plist in CopyFiles */,
                        );
                        runOnlyForDeploymentPostprocessing = 1;
                };
-               159D54D507529FFF004F8947 /* CopyFiles */ = {
+               15D54E2515B4FA1900F5229A /* com.apple.networking.IPMonitor */ = {
                        isa = PBXCopyFilesBuildPhase;
                        buildActionMask = 8;
-                       dstPath = /usr/share/man/man8;
+                       dstPath = /private/etc/asl;
                        dstSubfolderSpec = 0;
                        files = (
-                               159D54D607529FFF004F8947 /* configd.8 in CopyFiles */,
+                               15D54E2715B4FA4600F5229A /* com.apple.networking.IPMonitor in com.apple.networking.IPMonitor */,
                        );
+                       name = com.apple.networking.IPMonitor;
                        runOnlyForDeploymentPostprocessing = 1;
                };
-               159D54D707529FFF004F8947 /* CopyFiles */ = {
+               15D54E2A15B4FAF100F5229A /* com.apple.networking.IPMonitor */ = {
                        isa = PBXCopyFilesBuildPhase;
                        buildActionMask = 8;
-                       dstPath = /System/Library/LaunchDaemons;
+                       dstPath = /private/etc/asl;
                        dstSubfolderSpec = 0;
                        files = (
-                               1540E3610987DA9500157C07 /* com.apple.configd.plist in CopyFiles */,
+                               15D54E2B15B4FB0300F5229A /* com.apple.networking.IPMonitor in com.apple.networking.IPMonitor */,
                        );
+                       name = com.apple.networking.IPMonitor;
                        runOnlyForDeploymentPostprocessing = 1;
                };
-               15D9DCF910DD909F004E545D /* CopyFiles */ = {
+               15D9DCF910DD909F004E545D /* AppWorkaround.plist */ = {
                        isa = PBXCopyFilesBuildPhase;
                        buildActionMask = 8;
                        dstPath = /usr/local/AppSpecificWorkaround/SystemConfiguration;
                        dstSubfolderSpec = 0;
                        files = (
-                               15D9DCFB10DD90A1004E545D /* AppWorkaround.plist in CopyFiles */,
+                               15D9DCFB10DD90A1004E545D /* AppWorkaround.plist in AppWorkaround.plist */,
                        );
+                       name = AppWorkaround.plist;
                        runOnlyForDeploymentPostprocessing = 1;
                };
                15FF5C380CDF778F00EEC8AA /* CopyFiles */ = {
                1528BFE91357312E00691881 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Plugins/SCNetworkReachability/Info.plist; sourceTree = "<group>"; };
                1528BFF713573FEE00691881 /* libSCNetworkReachability.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSCNetworkReachability.a; sourceTree = BUILT_PRODUCTS_DIR; };
                1528BFFE13573FF500691881 /* SCNetworkReachability.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SCNetworkReachability.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
-               1528C0061357401900691881 /* libSCNetworkReachability.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSCNetworkReachability.a; sourceTree = BUILT_PRODUCTS_DIR; };
-               1528C00D1357401D00691881 /* SCNetworkReachability.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SCNetworkReachability.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
                152CEED0070CF6640050F23C /* libedit.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libedit.dylib; path = /usr/lib/libedit.2.dylib; sourceTree = "<absolute>"; };
                152E0E7E10FE820E00E402F2 /* helper.defs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.mig; name = helper.defs; path = SystemConfiguration.fproj/helper/helper.defs; sourceTree = "<group>"; };
                152E0E8810FE824000E402F2 /* helper_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = helper_types.h; path = SystemConfiguration.fproj/helper/helper_types.h; sourceTree = "<group>"; };
                1531D3DA0E93E6DA00248432 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Plugins/Logger/Info.plist; sourceTree = "<group>"; };
                1531D3DB0E93E6DA00248432 /* logger.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = logger.c; path = Plugins/Logger/logger.c; sourceTree = "<group>"; };
                1532629006281C9D00B1C10C /* dnsinfo_create.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = dnsinfo_create.h; path = dnsinfo/dnsinfo_create.h; sourceTree = "<group>"; };
+               153338BA14BE7978004FCE22 /* libSystemConfiguration_client.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = libSystemConfiguration_client.c; path = libSystemConfiguration/libSystemConfiguration_client.c; sourceTree = "<group>"; };
+               153338BB14BE7978004FCE22 /* libSystemConfiguration_client.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = libSystemConfiguration_client.h; path = libSystemConfiguration/libSystemConfiguration_client.h; sourceTree = "<group>"; };
                153393E20D34994100FE74E7 /* update-headers */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.perl; path = "update-headers"; sourceTree = "<group>"; };
+               153ACCA614E322D5005029A5 /* network_information_server.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; lineEnding = 0; name = network_information_server.c; path = nwi/network_information_server.c; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.c; };
+               153ACCA714E322D5005029A5 /* network_information_server.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = network_information_server.h; path = nwi/network_information_server.h; sourceTree = "<group>"; };
                1540E3600987DA9500157C07 /* com.apple.configd.plist */ = {isa = PBXFileReference; explicitFileType = text.plist.xml; fileEncoding = 30; path = com.apple.configd.plist; sourceTree = "<group>"; };
                1543636A0752D03C00A8EC6C /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = /System/Library/Frameworks/IOKit.framework; sourceTree = "<absolute>"; };
                1547001D08455B98006787CE /* SCHelper */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = SCHelper; sourceTree = BUILT_PRODUCTS_DIR; };
                156BD6BB07E0DFA9008698FF /* SCPreferencesSetSpecificPrivate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SCPreferencesSetSpecificPrivate.h; sourceTree = "<group>"; };
                156CA4850EF853BB00C59A18 /* Logger.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Logger.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
                156CA48D0EF853BB00C59A18 /* Info-Embedded.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "Info-Embedded.plist"; path = "Plugins/Logger/Info-Embedded.plist"; sourceTree = "<group>"; };
+               1572C57E171CCF9500870549 /* pppcontroller_mach_defines.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; name = pppcontroller_mach_defines.h; path = usr/local/include/ppp/pppcontroller_mach_defines.h; sourceTree = SDKROOT; };
                1572EB7A0A506D3B00D02459 /* smb-configuration.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = "smb-configuration.c"; sourceTree = "<group>"; };
+               15732AAC16EA503300F3AC4C /* configd_sim */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = configd_sim; sourceTree = BUILT_PRODUCTS_DIR; };
+               15732AD516EA511900F3AC4C /* scutil_sim */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = scutil_sim; sourceTree = BUILT_PRODUCTS_DIR; };
+               15732AE416EA6B6700F3AC4C /* libsystem_sim_configuration.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libsystem_sim_configuration.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
                157433EC0D4A8122002ACA73 /* scselect */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = scselect; sourceTree = BUILT_PRODUCTS_DIR; };
                1574341A0D4A8137002ACA73 /* scutil */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = scutil; sourceTree = BUILT_PRODUCTS_DIR; };
                1575FD2512CD15C60003D86E /* proxy-configuration.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "proxy-configuration.c"; sourceTree = "<group>"; };
                1575FD2612CD15C60003D86E /* proxy-configuration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "proxy-configuration.h"; sourceTree = "<group>"; };
                1577252F06EFB96700D7B52B /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/NetworkInterface.strings; sourceTree = "<group>"; };
-               157A84E80D56C63900B6F1A0 /* libdnsinfo.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libdnsinfo.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
+               157A84E80D56C63900B6F1A0 /* libsystem_configuration.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libsystem_configuration.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
                157A85020D56C7E800B6F1A0 /* libIPMonitor.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libIPMonitor.a; sourceTree = BUILT_PRODUCTS_DIR; };
                157A850D0D56C8AA00B6F1A0 /* libInterfaceNamer.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libInterfaceNamer.a; sourceTree = BUILT_PRODUCTS_DIR; };
                157A85230D56C8E000B6F1A0 /* libKernelEventMonitor.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libKernelEventMonitor.a; sourceTree = BUILT_PRODUCTS_DIR; };
                157A85440D56C96F00B6F1A0 /* libPreferencesMonitor.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPreferencesMonitor.a; sourceTree = BUILT_PRODUCTS_DIR; };
                157A88880A470D0F003A4256 /* SCSchemaDefinitionsPrivate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SCSchemaDefinitionsPrivate.h; sourceTree = "<group>"; };
                15828AE70753B5F900AD4710 /* KernelEventMonitor.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = KernelEventMonitor.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
-               1583EA10108395BB00A3BC0C /* libdnsinfo.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libdnsinfo.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
-               1583EA99108395BB00A3BC0C /* SystemConfiguration.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SystemConfiguration.framework; sourceTree = BUILT_PRODUCTS_DIR; };
-               1583EAAA108395BB00A3BC0C /* SCHelper */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = SCHelper; sourceTree = BUILT_PRODUCTS_DIR; };
-               1583EAD8108395BB00A3BC0C /* libIPMonitor.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libIPMonitor.a; sourceTree = BUILT_PRODUCTS_DIR; };
-               1583EADE108395BB00A3BC0C /* IPMonitor.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = IPMonitor.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
-               1583EAE7108395BB00A3BC0C /* libInterfaceNamer.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libInterfaceNamer.a; sourceTree = BUILT_PRODUCTS_DIR; };
-               1583EAED108395BC00A3BC0C /* InterfaceNamer.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = InterfaceNamer.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
-               1583EAFF108395BC00A3BC0C /* libKernelEventMonitor.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libKernelEventMonitor.a; sourceTree = BUILT_PRODUCTS_DIR; };
-               1583EB05108395BC00A3BC0C /* KernelEventMonitor.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = KernelEventMonitor.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
-               1583EB0E108395BC00A3BC0C /* libLinkConfiguration.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libLinkConfiguration.a; sourceTree = BUILT_PRODUCTS_DIR; };
-               1583EB14108395BC00A3BC0C /* LinkConfiguration.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = LinkConfiguration.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
-               1583EB21108395BC00A3BC0C /* Logger.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Logger.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
-               1583EB39108395BD00A3BC0C /* libPreferencesMonitor.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPreferencesMonitor.a; sourceTree = BUILT_PRODUCTS_DIR; };
-               1583EB3F108395BD00A3BC0C /* PreferencesMonitor.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PreferencesMonitor.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
-               1583EB84108395BD00A3BC0C /* configd */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = configd; sourceTree = BUILT_PRODUCTS_DIR; };
-               1583EB90108395BE00A3BC0C /* scselect */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = scselect; sourceTree = BUILT_PRODUCTS_DIR; };
-               1583EBB6108395BE00A3BC0C /* scutil */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = scutil; sourceTree = BUILT_PRODUCTS_DIR; };
                158AD8700754E3D400124717 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
                158AD8C00754E3EF00124717 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
                158AD9100754E40E00124717 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
-               158AD9F80754EA2F00124717 /* AppleTalk.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppleTalk.framework; path = /System/Library/Frameworks/AppleTalk.framework; sourceTree = "<absolute>"; };
+               1596A7AF14EDB73D00798C39 /* libSystemConfiguration_server.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; lineEnding = 0; name = libSystemConfiguration_server.c; path = libSystemConfiguration/libSystemConfiguration_server.c; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.c; };
+               1596A7B014EDB73D00798C39 /* libSystemConfiguration_server.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = libSystemConfiguration_server.h; path = libSystemConfiguration/libSystemConfiguration_server.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
                159A7513107FEAA400A57EAB /* VPNPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VPNPrivate.h; sourceTree = "<group>"; };
                159A7515107FEAA400A57EAB /* VPNConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VPNConfiguration.h; sourceTree = "<group>"; };
                159A7517107FEAA400A57EAB /* VPNPrivate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = VPNPrivate.c; sourceTree = "<group>"; };
                159A7519107FEAA400A57EAB /* VPNConfiguration.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = VPNConfiguration.c; sourceTree = "<group>"; };
+               159C9A8D17399609003DDA1D /* dnsinfo_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dnsinfo_internal.h; path = dnsinfo/dnsinfo_internal.h; sourceTree = "<group>"; };
                159D53A707528B36004F8947 /* ip_plugin.c */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = ip_plugin.c; sourceTree = "<group>"; };
                159D53AA07528B36004F8947 /* dns-configuration.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = "dns-configuration.c"; sourceTree = "<group>"; };
                159D53AB07528B36004F8947 /* set-hostname.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = "set-hostname.c"; sourceTree = "<group>"; };
                15AAA7F1108E310700C2A607 /* VPNTunnelPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VPNTunnelPrivate.h; sourceTree = "<group>"; };
                15AAA7F2108E310700C2A607 /* VPNTunnel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VPNTunnel.h; sourceTree = "<group>"; };
                15AAA7F3108E310700C2A607 /* VPNTunnel.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = VPNTunnel.c; sourceTree = "<group>"; };
+               15AB751916EBFF3400FAA8CE /* libSCNetworkReachability_sim.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSCNetworkReachability_sim.a; sourceTree = BUILT_PRODUCTS_DIR; };
+               15AB751F16EBFF8A00FAA8CE /* SCNetworkReachability.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SCNetworkReachability.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
+               15AC2D8816C574FE00340E28 /* libcupolicy.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libcupolicy.dylib; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.Internal.sdk/usr/lib/libcupolicy.dylib; sourceTree = DEVELOPER_DIR; };
                15AD7A380670A85900BFE03C /* SCNetworkConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SCNetworkConfiguration.h; sourceTree = "<group>"; };
                15AD7A390670A85900BFE03C /* SCNetworkConfigurationInternal.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = SCNetworkConfigurationInternal.c; sourceTree = "<group>"; };
                15AD7A3A0670A85900BFE03C /* SCNetworkConfigurationInternal.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SCNetworkConfigurationInternal.h; sourceTree = "<group>"; };
                15AD7A3C0670A85900BFE03C /* SCNetworkProtocol.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = SCNetworkProtocol.c; sourceTree = "<group>"; };
                15AD7A3D0670A85900BFE03C /* SCNetworkService.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = SCNetworkService.c; sourceTree = "<group>"; };
                15AD7A3E0670A85900BFE03C /* SCNetworkSet.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = SCNetworkSet.c; sourceTree = "<group>"; };
-               15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = AspenSDK.xcconfig; path = AppleInternal/XcodeConfig/AspenSDK.xcconfig; sourceTree = DEVELOPER_DIR; };
                15B686220678B65C00FF4023 /* NetworkConfiguration.plist */ = {isa = PBXFileReference; explicitFileType = text.plist.xml; fileEncoding = 4; path = NetworkConfiguration.plist; sourceTree = "<group>"; };
                15B73F0805FD1B670096477F /* dnsinfo_copy.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = dnsinfo_copy.c; path = dnsinfo/dnsinfo_copy.c; sourceTree = "<group>"; };
                15B73F0905FD1B670096477F /* dnsinfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = dnsinfo.h; path = dnsinfo/dnsinfo.h; sourceTree = "<group>"; };
-               15B73F0B05FD1B670096477F /* dnsinfo_private.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = dnsinfo_private.c; path = dnsinfo/dnsinfo_private.c; sourceTree = "<group>"; };
                15B73F0C05FD1B670096477F /* dnsinfo_private.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = dnsinfo_private.h; path = dnsinfo/dnsinfo_private.h; sourceTree = "<group>"; };
                15B73F0D05FD1B670096477F /* dnsinfo_server.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = dnsinfo_server.c; path = dnsinfo/dnsinfo_server.c; sourceTree = "<group>"; };
                15B73F0E05FD1B670096477F /* dnsinfo_server.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = dnsinfo_server.h; path = dnsinfo/dnsinfo_server.h; sourceTree = "<group>"; };
                15BAA32207F0699A00D9EC95 /* libbsm.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libbsm.dylib; path = /usr/lib/libbsm.dylib; sourceTree = "<absolute>"; };
                15C330B7134B92780028E36B /* SCNetworkReachabilityServer_client.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SCNetworkReachabilityServer_client.c; path = reachability/SCNetworkReachabilityServer_client.c; sourceTree = "<group>"; };
-               15C330B8134B92780028E36B /* rb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = rb.c; path = reachability/rb.c; sourceTree = "<group>"; };
-               15C330B9134B92780028E36B /* rb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = rb.h; path = reachability/rb.h; sourceTree = "<group>"; };
                15C330BB134B92780028E36B /* SCNetworkReachabilityServer_server.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SCNetworkReachabilityServer_server.c; path = reachability/SCNetworkReachabilityServer_server.c; sourceTree = "<group>"; };
                15C330D0134B95AA0028E36B /* SCNetworkReachabilityInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCNetworkReachabilityInternal.h; sourceTree = "<group>"; };
+               15CAEF381712690500367CE1 /* libcupolicy.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libcupolicy.dylib; path = Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator7.0.sdk/usr/local/lib/libcupolicy.dylib; sourceTree = DEVELOPER_DIR; };
                15CB691305C0722B0099E85F /* SystemConfiguration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SystemConfiguration.h; sourceTree = "<group>"; };
                15CB691505C0722B0099E85F /* SCPrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SCPrivate.h; sourceTree = "<group>"; };
                15CB691705C0722B0099E85F /* SCDPlugin.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SCDPlugin.h; sourceTree = "<group>"; };
                15CB694105C0722B0099E85F /* moh_msg.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = moh_msg.h; sourceTree = "<group>"; };
                15CB694305C0722B0099E85F /* moh.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = moh.h; sourceTree = "<group>"; };
                15CB694505C0722B0099E85F /* DeviceOnHold.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DeviceOnHold.h; sourceTree = "<group>"; };
-               15CB694705C0722B0099E85F /* LinkConfiguration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LinkConfiguration.h; sourceTree = "<group>"; };
                15CB694905C0722B0099E85F /* dy_framework.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dy_framework.h; sourceTree = "<group>"; };
                15CB695005C0722B0099E85F /* SCD.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SCD.c; sourceTree = "<group>"; };
                15CB695205C0722B0099E85F /* SCDKeys.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SCDKeys.c; sourceTree = "<group>"; };
                15CB69A005C0722B0099E85F /* SCLocation.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SCLocation.c; sourceTree = "<group>"; };
                15CB69A205C0722B0099E85F /* SCNetwork.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SCNetwork.c; sourceTree = "<group>"; };
                15CB69A405C0722B0099E85F /* SCNetworkConnection.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SCNetworkConnection.c; sourceTree = "<group>"; };
-               15CB69A605C0722B0099E85F /* SCNetworkReachability.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SCNetworkReachability.c; sourceTree = "<group>"; };
+               15CB69A605C0722B0099E85F /* SCNetworkReachability.c */ = {isa = PBXFileReference; indentWidth = 8; lastKnownFileType = sourcecode.c.c; path = SCNetworkReachability.c; sourceTree = "<group>"; };
                15CB69A805C0722B0099E85F /* SCProxies.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SCProxies.c; sourceTree = "<group>"; };
                15CB69AC05C0722B0099E85F /* DHCP.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = DHCP.c; sourceTree = "<group>"; };
                15CB69AE05C0722B0099E85F /* moh.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = moh.c; sourceTree = "<group>"; };
                15CB6A6A05C0722B0099E85F /* scutil.8 */ = {isa = PBXFileReference; explicitFileType = text.man; path = scutil.8; sourceTree = "<group>"; };
                15CB6A6F05C0722B0099E85F /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = "<absolute>"; };
                15CFC229068B222F00123568 /* get-mobility-info */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.sh; path = "get-mobility-info"; sourceTree = SOURCE_ROOT; };
+               15D3082716F3E4DA00014F82 /* libSimulatorSupport_sim.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSimulatorSupport_sim.a; sourceTree = BUILT_PRODUCTS_DIR; };
+               15D3082D16F3E4E100014F82 /* SimulatorSupport.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SimulatorSupport.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
+               15D3083616F3EB7200014F82 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Plugins/SimulatorSupport/Info.plist; sourceTree = "<group>"; };
+               15D3083816F3EB8600014F82 /* simulator_support.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = simulator_support.c; path = Plugins/SimulatorSupport/simulator_support.c; sourceTree = "<group>"; };
+               15D3083A16F4E6D900014F82 /* com.apple.configd_sim.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.configd_sim.plist; sourceTree = "<group>"; };
                15D8B2291450D8450090CECF /* SCD.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCD.h; sourceTree = "<group>"; };
                15D9DCFA10DD90A1004E545D /* AppWorkaround.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = AppWorkaround.plist; sourceTree = "<group>"; };
-               15DAD5EE075913CE0084A6ED /* libdnsinfo.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libdnsinfo.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
+               15DAD5EE075913CE0084A6ED /* libsystem_configuration.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libsystem_configuration.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
                15DAF2D808466D4900D1B2BD /* SCHelper_client.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = SCHelper_client.c; path = helper/SCHelper_client.c; sourceTree = "<group>"; };
                15DAF2D908466D4900D1B2BD /* SCHelper_server.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = SCHelper_server.c; path = helper/SCHelper_server.c; sourceTree = "<group>"; };
                15DC34670711D49400A3311C /* net_interface.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = net_interface.c; sourceTree = "<group>"; };
                15DC346C0711D49400A3311C /* net_service.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = net_service.h; sourceTree = "<group>"; };
                15DC346D0711D49400A3311C /* net_set.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = net_set.c; sourceTree = "<group>"; };
                15DC346E0711D49400A3311C /* net_set.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = net_set.h; sourceTree = "<group>"; };
+               15E1B05916EBAE3C00E5F06F /* libIPMonitor_sim.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libIPMonitor_sim.a; sourceTree = BUILT_PRODUCTS_DIR; };
+               15E1B06116EBAE7800E5F06F /* IPMonitor.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = IPMonitor.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
                15FC12F20CCEA4F00013872C /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = SCMonitor/Info.plist; sourceTree = "<group>"; };
                15FC130A0CCEA59E0013872C /* monitor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = monitor.c; path = SCMonitor/monitor.c; sourceTree = "<group>"; };
-               15FCAACF05FD0EBF00CB79E6 /* shared_dns_info_types.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = shared_dns_info_types.h; path = dnsinfo/shared_dns_info_types.h; sourceTree = SOURCE_ROOT; };
-               15FCAAD005FD0EBF00CB79E6 /* shared_dns_info.defs */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.mig; name = shared_dns_info.defs; path = dnsinfo/shared_dns_info.defs; sourceTree = "<group>"; };
                15FD147B0D594FE700F9409C /* IndigoSDK.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = IndigoSDK.xcconfig; path = /AppleInternal/Indigo/IndigoSDK.xcconfig; sourceTree = "<absolute>"; };
                15FD72970754DA2B001CC321 /* InterfaceNamer.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = InterfaceNamer.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
                15FD72A50754DA4C001CC321 /* IPMonitor.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = IPMonitor.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
                23C1E2BE062DD5DB00835B54 /* pppcontroller.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = pppcontroller.h; path = configd.build/SystemConfiguration.framework.build/DerivedSources/pppcontroller.h; sourceTree = BUILT_PRODUCTS_DIR; };
                72B43726113C7BFC00EBF1B6 /* nc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nc.h; sourceTree = "<group>"; };
                72B43727113C7BFC00EBF1B6 /* nc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nc.c; sourceTree = "<group>"; };
+               72C3E82615003E78000D68CB /* MobileInstallation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileInstallation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.Internal.sdk/System/Library/PrivateFrameworks/MobileInstallation.framework; sourceTree = DEVELOPER_DIR; };
                9EE943F306AF409B00772EB5 /* BondConfiguration.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = BondConfiguration.c; sourceTree = "<group>"; };
+               B03FEFB516376D2800A1B88F /* VPNAppLayer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = VPNAppLayer.c; sourceTree = "<group>"; };
+               B084710E16385121006C92A3 /* SCNetworkConnectionInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCNetworkConnectionInternal.h; sourceTree = "<group>"; };
+               B0A88CA616397A1200A60B3A /* VPNAppLayerPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = VPNAppLayerPrivate.h; sourceTree = "<group>"; tabWidth = 4; };
+               B0BF3440174594C400961734 /* entitlements-osx.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "entitlements-osx.plist"; sourceTree = "<group>"; };
+               B0C967F717441F0E00889853 /* SNHelperPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNHelperPrivate.h; sourceTree = "<group>"; };
+               B0C9689B174426C200889853 /* SNHelper.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SNHelper.c; sourceTree = "<group>"; };
+               C4CDB8111631933400819B44 /* VPNFlow.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = VPNFlow.h; sourceTree = "<group>"; tabWidth = 4; };
+               C4CDB8121631933400819B44 /* VPNFlowPrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VPNFlowPrivate.h; sourceTree = "<group>"; };
+               C4CDB8141631935700819B44 /* VPNFlow.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = VPNFlow.c; sourceTree = "<group>"; tabWidth = 4; };
+               C4F1847F16237AFC00D97043 /* VPNService.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = VPNService.c; sourceTree = "<group>"; };
+               D61AAEAD1522C99C0066B003 /* scprefs_observer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = scprefs_observer.c; sourceTree = "<group>"; };
+               D61AAEB41522C9BD0066B003 /* scprefs_observer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = scprefs_observer.h; sourceTree = "<group>"; };
+               D68AD25F159BCD5900D4F1BE /* com.apple.networking.IPMonitor */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = com.apple.networking.IPMonitor; sourceTree = "<group>"; };
                D6986A75136891120091C931 /* network_information_priv.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = network_information_priv.c; path = nwi/network_information_priv.c; sourceTree = "<group>"; };
                D6986A761368911E0091C931 /* network_information_priv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = network_information_priv.h; path = nwi/network_information_priv.h; sourceTree = "<group>"; };
                D6986A77136891300091C931 /* network_information.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = network_information.c; path = nwi/network_information.c; sourceTree = "<group>"; };
                D6986A781368913C0091C931 /* network_information.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = network_information.h; path = nwi/network_information.h; sourceTree = "<group>"; };
+               D6AEB89815AE4446009F2FAF /* ip_plugin.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ip_plugin.h; sourceTree = "<group>"; };
                F95B8A420B03E07A00993BA3 /* SCNetworkSignature.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = SCNetworkSignature.c; sourceTree = "<group>"; };
                F95B8A440B03E09300993BA3 /* SCNetworkSignature.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SCNetworkSignature.h; sourceTree = "<group>"; };
                F95B8A450B03E09300993BA3 /* SCNetworkSignaturePrivate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SCNetworkSignaturePrivate.h; sourceTree = "<group>"; };
+               F9A3780E16A4846E00C57CDC /* IPMonitorControlPrefs.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = IPMonitorControlPrefs.c; sourceTree = "<group>"; };
+               F9A3780F16A4846E00C57CDC /* IPMonitorControlPrefs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IPMonitorControlPrefs.h; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
                        files = (
                                1558481907550EC10046C2E9 /* CoreFoundation.framework in Frameworks */,
                                1559C44E0D349A4E0098FD59 /* SystemConfiguration.framework in Frameworks */,
+                               15D2E437167643460078F547 /* Security.framework in Frameworks */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        buildActionMask = 2147483647;
                        files = (
                                1572C5240CFB55B400E2776E /* CoreFoundation.framework in Frameworks */,
+                               B03FEFBB16382C1300A1B88F /* libbsm.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               15732A9B16EA503200F3AC4C /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               15732A9C16EA503200F3AC4C /* CoreFoundation.framework in Frameworks */,
+                               15732A9D16EA503200F3AC4C /* SystemConfiguration.framework in Frameworks */,
+                               15732A9E16EA503200F3AC4C /* IOKit.framework in Frameworks */,
+                               15732A9F16EA503200F3AC4C /* Security.framework in Frameworks */,
+                               15732AA016EA503200F3AC4C /* libbsm.dylib in Frameworks */,
+                               15AB752D16EC2AE900FAA8CE /* libIPMonitor_sim.a in Frameworks */,
+                               15AB752E16EC2AE900FAA8CE /* libSCNetworkReachability_sim.a in Frameworks */,
+                               15D3083316F3EB0700014F82 /* libSimulatorSupport_sim.a in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               15732ACD16EA511900F3AC4C /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               15732ACE16EA511900F3AC4C /* CoreFoundation.framework in Frameworks */,
+                               15732ACF16EA511900F3AC4C /* SystemConfiguration.framework in Frameworks */,
+                               15732AD016EA511900F3AC4C /* libedit.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               15732AE016EA6B6700F3AC4C /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                1574340E0D4A8137002ACA73 /* CoreFoundation.framework in Frameworks */,
                                1574340F0D4A8137002ACA73 /* SystemConfiguration.framework in Frameworks */,
                                157434110D4A8137002ACA73 /* libedit.dylib in Frameworks */,
+                               72C3E82715003E78000D68CB /* MobileInstallation.framework in Frameworks */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
-               1583EA0C108395BB00A3BC0C /* Frameworks */ = {
-                       isa = PBXFrameworksBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               1583EA93108395BB00A3BC0C /* Frameworks */ = {
-                       isa = PBXFrameworksBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               1583EA94108395BB00A3BC0C /* CoreFoundation.framework in Frameworks */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               1583EAA1108395BB00A3BC0C /* Frameworks */ = {
-                       isa = PBXFrameworksBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               1583EAA2108395BB00A3BC0C /* CoreFoundation.framework in Frameworks */,
-                               1583EAA3108395BB00A3BC0C /* SystemConfiguration.framework in Frameworks */,
-                               1583EAA4108395BB00A3BC0C /* Security.framework in Frameworks */,
-                               15F21619110F826800E89CF7 /* libbsm.dylib in Frameworks */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               1583EB19108395BC00A3BC0C /* Frameworks */ = {
-                       isa = PBXFrameworksBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               1583EB1A108395BC00A3BC0C /* CoreFoundation.framework in Frameworks */,
-                               1583EB1B108395BC00A3BC0C /* SystemConfiguration.framework in Frameworks */,
-                               1583EB1C108395BC00A3BC0C /* IOKit.framework in Frameworks */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               1583EB73108395BD00A3BC0C /* Frameworks */ = {
-                       isa = PBXFrameworksBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               1583EB74108395BD00A3BC0C /* CoreFoundation.framework in Frameworks */,
-                               1583EB75108395BD00A3BC0C /* SystemConfiguration.framework in Frameworks */,
-                               1583EB76108395BD00A3BC0C /* IOKit.framework in Frameworks */,
-                               1583EB77108395BD00A3BC0C /* Security.framework in Frameworks */,
-                               1583EB78108395BD00A3BC0C /* libbsm.dylib in Frameworks */,
-                               1583EB79108395BD00A3BC0C /* libKernelEventMonitor.a in Frameworks */,
-                               1583EB7A108395BD00A3BC0C /* libInterfaceNamer.a in Frameworks */,
-                               1583EB7B108395BD00A3BC0C /* libIPMonitor.a in Frameworks */,
-                               1583EB7C108395BD00A3BC0C /* libLinkConfiguration.a in Frameworks */,
-                               1583EB7E108395BD00A3BC0C /* libPreferencesMonitor.a in Frameworks */,
-                               1528C01A135746D700691881 /* libSCNetworkReachability.a in Frameworks */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               1583EB8A108395BE00A3BC0C /* Frameworks */ = {
-                       isa = PBXFrameworksBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               1583EB8B108395BE00A3BC0C /* CoreFoundation.framework in Frameworks */,
-                               1583EB8C108395BE00A3BC0C /* SystemConfiguration.framework in Frameworks */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               1583EBAF108395BE00A3BC0C /* Frameworks */ = {
-                       isa = PBXFrameworksBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               1583EBB0108395BE00A3BC0C /* CoreFoundation.framework in Frameworks */,
-                               1583EBB1108395BE00A3BC0C /* SystemConfiguration.framework in Frameworks */,
-                               1583EBB2108395BE00A3BC0C /* libedit.dylib in Frameworks */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
                159D54CA07529FFF004F8947 /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        buildActionMask = 2147483647;
                        files = (
                                15A5A2630D5B94190087BDA0 /* CoreFoundation.framework in Frameworks */,
+                               B0FEF41A164406F400174B99 /* libbsm.dylib in Frameworks */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        buildActionMask = 2147483647;
                        files = (
                                15DAD6AE07591A1A0084A6ED /* CoreFoundation.framework in Frameworks */,
+                               B03FEFBA16382C0700A1B88F /* libbsm.dylib in Frameworks */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
-               1513E399108420A700088779 /* EmbeddedOther */ = {
-                       isa = PBXGroup;
-                       children = (
-                               1583EA10108395BB00A3BC0C /* libdnsinfo.dylib */,
-                               1583EA99108395BB00A3BC0C /* SystemConfiguration.framework */,
-                               1513E39D108420DE00088779 /* Plugins */,
-                               1583EAAA108395BB00A3BC0C /* SCHelper */,
-                               1513E3A11084216500088779 /* configd, scutil, scselect */,
-                       );
-                       name = EmbeddedOther;
-                       sourceTree = "<group>";
-               };
-               1513E39D108420DE00088779 /* Plugins */ = {
-                       isa = PBXGroup;
-                       children = (
-                               1583EAD8108395BB00A3BC0C /* libIPMonitor.a */,
-                               1583EADE108395BB00A3BC0C /* IPMonitor.bundle */,
-                               1583EAE7108395BB00A3BC0C /* libInterfaceNamer.a */,
-                               1583EAED108395BC00A3BC0C /* InterfaceNamer.bundle */,
-                               1583EAFF108395BC00A3BC0C /* libKernelEventMonitor.a */,
-                               1583EB05108395BC00A3BC0C /* KernelEventMonitor.bundle */,
-                               1583EB0E108395BC00A3BC0C /* libLinkConfiguration.a */,
-                               1583EB14108395BC00A3BC0C /* LinkConfiguration.bundle */,
-                               1583EB21108395BC00A3BC0C /* Logger.bundle */,
-                               1583EB39108395BD00A3BC0C /* libPreferencesMonitor.a */,
-                               1583EB3F108395BD00A3BC0C /* PreferencesMonitor.bundle */,
-                               1528C0061357401900691881 /* libSCNetworkReachability.a */,
-                               1528C00D1357401D00691881 /* SCNetworkReachability.bundle */,
-                       );
-                       name = Plugins;
-                       sourceTree = "<group>";
-               };
-               1513E3A11084216500088779 /* configd, scutil, scselect */ = {
-                       isa = PBXGroup;
-                       children = (
-                               1583EB84108395BD00A3BC0C /* configd */,
-                               1583EB90108395BE00A3BC0C /* scselect */,
-                               1583EBB6108395BE00A3BC0C /* scutil */,
-                       );
-                       name = "configd, scutil, scselect";
-                       sourceTree = "<group>";
-               };
                151F5DA80CCE995D0093AC3B /* SCMonitor */ = {
                        isa = PBXGroup;
                        children = (
                154083530D5B824400E07907 /* MacOSX */ = {
                        isa = PBXGroup;
                        children = (
-                               15DAD5EE075913CE0084A6ED /* libdnsinfo.dylib */,
+                               15DAD5EE075913CE0084A6ED /* libsystem_configuration.dylib */,
                                1547072E0D1F70C80075C28D /* SystemConfiguration.framework */,
                                1547001D08455B98006787CE /* SCHelper */,
                                151F5D9A0CCE98E50093AC3B /* SCMonitor.plugin */,
                1540835A0D5B825200E07907 /* Embedded */ = {
                        isa = PBXGroup;
                        children = (
-                               157A84E80D56C63900B6F1A0 /* libdnsinfo.dylib */,
+                               157A84E80D56C63900B6F1A0 /* libsystem_configuration.dylib */,
                                1559C4440D349A4E0098FD59 /* SystemConfiguration.framework */,
                                154083C50D5B832F00E07907 /* Plugins */,
                                1559C4470D349A4E0098FD59 /* SCHelper */,
                        isa = PBXGroup;
                        children = (
                                15A5A26A0D5B94190087BDA0 /* SystemConfiguration.framework */,
+                               1541472016EBF5C500B197B9 /* Plugins */,
+                               1541471F16EBF32B00B197B9 /* configd, scutil */,
                        );
                        name = EmbeddedSimulator;
                        sourceTree = "<group>";
                        name = "configd, scutil, scselect";
                        sourceTree = "<group>";
                };
+               1541471F16EBF32B00B197B9 /* configd, scutil */ = {
+                       isa = PBXGroup;
+                       children = (
+                       );
+                       name = "configd, scutil";
+                       sourceTree = "<group>";
+               };
+               1541472016EBF5C500B197B9 /* Plugins */ = {
+                       isa = PBXGroup;
+                       children = (
+                       );
+                       name = Plugins;
+                       sourceTree = "<group>";
+               };
                1547002E084561B4006787CE /* SCHelper */ = {
                        isa = PBXGroup;
                        children = (
                        children = (
                                15B73F0905FD1B670096477F /* dnsinfo.h */,
                                1532629006281C9D00B1C10C /* dnsinfo_create.h */,
+                               159C9A8D17399609003DDA1D /* dnsinfo_internal.h */,
                                15B73F0C05FD1B670096477F /* dnsinfo_private.h */,
                                15B73F0E05FD1B670096477F /* dnsinfo_server.h */,
                        );
                1582B37905FD1A66009C2750 /* Sources */ = {
                        isa = PBXGroup;
                        children = (
-                               15B73F0B05FD1B670096477F /* dnsinfo_private.c */,
                                15B73F0805FD1B670096477F /* dnsinfo_copy.c */,
                                1521FC5C060F296A003B28F5 /* dnsinfo_create.c */,
                                1522FCE50FA7FD7000B24128 /* dnsinfo_flatfile.c */,
                                1531D3D90E93E6AA00248432 /* Logger */,
                                159D53C207528B36004F8947 /* PreferencesMonitor */,
                                1528BFDA13572FC200691881 /* SCNetworkReachability */,
+                               15D3080E16F3E49F00014F82 /* SimulatorSupport */,
                        );
                        name = Plugins;
                        sourceTree = "<group>";
                159D53A607528B36004F8947 /* IPMonitor */ = {
                        isa = PBXGroup;
                        children = (
+                               D6AEB89815AE4446009F2FAF /* ip_plugin.h */,
                                159D53A707528B36004F8947 /* ip_plugin.c */,
                                155D22380AF13A7300D52ED0 /* dns-configuration.h */,
                                159D53AA07528B36004F8947 /* dns-configuration.c */,
                                155D223A0AF13A7300D52ED0 /* smb-configuration.h */,
                                1572EB7A0A506D3B00D02459 /* smb-configuration.c */,
                                15FD743E0754DE7A001CC321 /* Info.plist */,
+                               D68AD25F159BCD5900D4F1BE /* com.apple.networking.IPMonitor */,
                        );
                        name = IPMonitor;
                        path = Plugins/IPMonitor;
                159D53C907528B36004F8947 /* common */ = {
                        isa = PBXGroup;
                        children = (
+                               F9A3780E16A4846E00C57CDC /* IPMonitorControlPrefs.c */,
+                               F9A3780F16A4846E00C57CDC /* IPMonitorControlPrefs.h */,
                                159D53CA07528B36004F8947 /* cache.c */,
                                159D53CB07528B36004F8947 /* cache.h */,
                        );
                        path = Plugins/common;
                        sourceTree = "<group>";
                };
+               15B534AD14BE778800EA6522 /* libsystem_configuration */ = {
+                       isa = PBXGroup;
+                       children = (
+                               153338BB14BE7978004FCE22 /* libSystemConfiguration_client.h */,
+                               153338BA14BE7978004FCE22 /* libSystemConfiguration_client.c */,
+                               1596A7B014EDB73D00798C39 /* libSystemConfiguration_server.h */,
+                               1596A7AF14EDB73D00798C39 /* libSystemConfiguration_server.c */,
+                               1582B36B05FD1A4D009C2750 /* DNSConfiguration */,
+                               D6986A70136890B60091C931 /* NetworkInformation */,
+                       );
+                       name = libsystem_configuration;
+                       sourceTree = "<group>";
+               };
                15B6861D0678B61900FF4023 /* Supporting Files */ = {
                        isa = PBXGroup;
                        children = (
                        children = (
                                15CB693705C0722B0099E85F /* SCNetworkReachability.h */,
                                15C330D0134B95AA0028E36B /* SCNetworkReachabilityInternal.h */,
-                               15C330B9134B92780028E36B /* rb.h */,
                        );
                        name = Headers;
                        sourceTree = "<group>";
                                15CB69A605C0722B0099E85F /* SCNetworkReachability.c */,
                                15C330B7134B92780028E36B /* SCNetworkReachabilityServer_client.c */,
                                15C330BB134B92780028E36B /* SCNetworkReachabilityServer_server.c */,
-                               15C330B8134B92780028E36B /* rb.c */,
                        );
                        name = Sources;
                        sourceTree = "<group>";
                                15AD7A380670A85900BFE03C /* SCNetworkConfiguration.h */,
                                155A1E6B081079CC00F70D98 /* SCNetworkConfigurationPrivate.h */,
                                15AD7A3A0670A85900BFE03C /* SCNetworkConfigurationInternal.h */,
-                               15CB694705C0722B0099E85F /* LinkConfiguration.h */,
                        );
                        name = Headers;
                        sourceTree = "<group>";
                                9EE943F306AF409B00772EB5 /* BondConfiguration.c */,
                                15FD7B3B101E439200C56621 /* BridgeConfiguration.c */,
                                15CB69B605C0722B0099E85F /* VLANConfiguration.c */,
+                               C4F1847F16237AFC00D97043 /* VPNService.c */,
                        );
                        name = Sources;
                        sourceTree = "<group>";
                15C330E0134B9C4C0028E36B /* Headers */ = {
                        isa = PBXGroup;
                        children = (
+                               B084710E16385121006C92A3 /* SCNetworkConnectionInternal.h */,
                                15CB693505C0722B0099E85F /* SCNetworkConnection.h */,
                                15A2972E0A13C08C009879B3 /* SCNetworkConnectionPrivate.h */,
                                23C1E2BE062DD5DB00835B54 /* pppcontroller.h */,
                15C330E2134B9C9B0028E36B /* Sources */ = {
                        isa = PBXGroup;
                        children = (
+                               B0C9689B174426C200889853 /* SNHelper.c */,
+                               B03FEFB516376D2800A1B88F /* VPNAppLayer.c */,
+                               C4CDB8141631935700819B44 /* VPNFlow.c */,
                                159A7517107FEAA400A57EAB /* VPNPrivate.c */,
                                159A7519107FEAA400A57EAB /* VPNConfiguration.c */,
                                15AAA7F3108E310700C2A607 /* VPNTunnel.c */,
                15C330E3134B9CA30028E36B /* Headers */ = {
                        isa = PBXGroup;
                        children = (
+                               B0C967F717441F0E00889853 /* SNHelperPrivate.h */,
+                               B0A88CA616397A1200A60B3A /* VPNAppLayerPrivate.h */,
+                               C4CDB8111631933400819B44 /* VPNFlow.h */,
+                               C4CDB8121631933400819B44 /* VPNFlowPrivate.h */,
                                159A7513107FEAA400A57EAB /* VPNPrivate.h */,
                                159A7515107FEAA400A57EAB /* VPNConfiguration.h */,
                                15AAA7F2108E310700C2A607 /* VPNTunnel.h */,
                        children = (
                                15CB6A8605C072500099E85F /* MiG */,
                                15CB6A8305C072410099E85F /* Schema */,
-                               D6986A70136890B60091C931 /* NetworkInformation */,
-                               1582B36B05FD1A4D009C2750 /* DNSConfiguration */,
+                               15B534AD14BE778800EA6522 /* libsystem_configuration */,
                                15CB690705C0722A0099E85F /* SystemConfiguration */,
                                151F5DA80CCE995D0093AC3B /* SCMonitor */,
                                15CB69C205C0722B0099E85F /* configd */,
                                159D53A207528B06004F8947 /* Plugins */,
                                15CB6A6E05C0722B0099E85F /* External Frameworks and Libraries */,
                                15CB690F05C0722B0099E85F /* Products */,
-                               15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */,
                                15FD147B0D594FE700F9409C /* IndigoSDK.xcconfig */,
                        );
                        indentWidth = 8;
                                154083530D5B824400E07907 /* MacOSX */,
                                1540835A0D5B825200E07907 /* Embedded */,
                                154083890D5B82A900E07907 /* EmbeddedSimulator */,
-                               1513E399108420A700088779 /* EmbeddedOther */,
+                               15732AAC16EA503300F3AC4C /* configd_sim */,
+                               15732AD516EA511900F3AC4C /* scutil_sim */,
+                               15732AE416EA6B6700F3AC4C /* libsystem_sim_configuration.dylib */,
+                               15E1B05916EBAE3C00E5F06F /* libIPMonitor_sim.a */,
+                               15E1B06116EBAE7800E5F06F /* IPMonitor.bundle */,
+                               15AB751916EBFF3400FAA8CE /* libSCNetworkReachability_sim.a */,
+                               15AB751F16EBFF8A00FAA8CE /* SCNetworkReachability.bundle */,
+                               15D3082716F3E4DA00014F82 /* libSimulatorSupport_sim.a */,
+                               15D3082D16F3E4E100014F82 /* SimulatorSupport.bundle */,
                        );
                        name = Products;
                        sourceTree = "<group>";
                                15CB694505C0722B0099E85F /* DeviceOnHold.h */,
                                15CB693D05C0722B0099E85F /* DHCPClientPreferences.h */,
                                15CB694905C0722B0099E85F /* dy_framework.h */,
+                               D61AAEB41522C9BD0066B003 /* scprefs_observer.h */,
                                15CB694305C0722B0099E85F /* moh.h */,
                                15CB694105C0722B0099E85F /* moh_msg.h */,
                        );
                        children = (
                                150607BD075A00A200B147BA /* SCSchemaDefinitions.c */,
                                15CB695005C0722B0099E85F /* SCD.c */,
+                               D61AAEAD1522C99C0066B003 /* scprefs_observer.c */,
                                15CB695405C0722B0099E85F /* SCDPrivate.c */,
                                15CB695605C0722B0099E85F /* SCDPlugin.c */,
                                15CB699C05C0722B0099E85F /* SCDConsoleUser.c */,
                15CB6A1805C0722B0099E85F /* Supporting Files */ = {
                        isa = PBXGroup;
                        children = (
+                               B0BF3440174594C400961734 /* entitlements-osx.plist */,
                                1540E3600987DA9500157C07 /* com.apple.configd.plist */,
+                               15D3083A16F4E6D900014F82 /* com.apple.configd_sim.plist */,
                                15CB6A2005C0722B0099E85F /* configd.8 */,
                                1567333E0DD1FD6500145179 /* entitlements.plist */,
                        );
                15CB6A6E05C0722B0099E85F /* External Frameworks and Libraries */ = {
                        isa = PBXGroup;
                        children = (
-                               158AD9F80754EA2F00124717 /* AppleTalk.framework */,
                                15FEE80D0CCFD341001312F9 /* ApplicationServices.framework */,
                                15CB6A6F05C0722B0099E85F /* CoreFoundation.framework */,
                                1543636A0752D03C00A8EC6C /* IOKit.framework */,
                                1520A3DE0846B2DC0010B584 /* Security.framework */,
                                15BAA32207F0699A00D9EC95 /* libbsm.dylib */,
+                               15AC2D8816C574FE00340E28 /* libcupolicy.dylib */,
                                152CEED0070CF6640050F23C /* libedit.dylib */,
+                               72C3E82615003E78000D68CB /* MobileInstallation.framework */,
+                               15CAEF381712690500367CE1 /* libcupolicy.dylib */,
                        );
                        name = "External Frameworks and Libraries";
                        sourceTree = "<group>";
                                1514D76D05C08A5F00757DC9 /* config_types.h */,
                                152E0E7E10FE820E00E402F2 /* helper.defs */,
                                152E0E8810FE824000E402F2 /* helper_types.h */,
-                               15FCAAD005FD0EBF00CB79E6 /* shared_dns_info.defs */,
-                               15FCAACF05FD0EBF00CB79E6 /* shared_dns_info_types.h */,
                                23C1E2B8062DD45900835B54 /* pppcontroller.defs */,
                                23C1E2B4062DD2C700835B54 /* pppcontroller_types.h */,
+                               1572C57E171CCF9500870549 /* pppcontroller_mach_defines.h */,
                        );
                        name = MiG;
                        sourceTree = "<group>";
                };
+               15D3080E16F3E49F00014F82 /* SimulatorSupport */ = {
+                       isa = PBXGroup;
+                       children = (
+                               15D3083816F3EB8600014F82 /* simulator_support.c */,
+                               15D3083616F3EB7200014F82 /* Info.plist */,
+                       );
+                       name = SimulatorSupport;
+                       sourceTree = "<group>";
+               };
                15FF5C390CDF9C4000EEC8AA /* Supporting Files */ = {
                        isa = PBXGroup;
                        children = (
                        children = (
                                D6986A781368913C0091C931 /* network_information.h */,
                                D6986A761368911E0091C931 /* network_information_priv.h */,
+                               153ACCA714E322D5005029A5 /* network_information_server.h */,
                        );
                        name = Headers;
                        sourceTree = "<group>";
                        children = (
                                D6986A77136891300091C931 /* network_information.c */,
                                D6986A75136891120091C931 /* network_information_priv.c */,
+                               153ACCA614E322D5005029A5 /* network_information_server.c */,
                        );
                        name = Sources;
                        sourceTree = "<group>";
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
-               1528C0001357401900691881 /* Headers */ = {
-                       isa = PBXHeadersBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
                1547001908455B98006787CE /* Headers */ = {
                        isa = PBXHeadersBuildPhase;
                        buildActionMask = 2147483647;
                                1572C4B80CFB55B400E2776E /* SCPreferencesSetSpecific.h in Headers */,
                                1572C4B90CFB55B400E2776E /* SCNetworkConfiguration.h in Headers */,
                                1572C4BA0CFB55B400E2776E /* SCNetworkConfigurationInternal.h in Headers */,
+                               D61AAEB61522C9E60066B003 /* scprefs_observer.h in Headers */,
                                1572C4BB0CFB55B400E2776E /* SCNetwork.h in Headers */,
                                1572C4BC0CFB55B400E2776E /* SCNetworkConnection.h in Headers */,
                                1572C4BD0CFB55B400E2776E /* SCNetworkReachability.h in Headers */,
                                1572C4C00CFB55B400E2776E /* SCDynamicStoreCopyDHCPInfo.h in Headers */,
                                1572C4C10CFB55B400E2776E /* moh_msg.h in Headers */,
                                1572C4C20CFB55B400E2776E /* moh.h in Headers */,
+                               C4CDB81A163193AF00819B44 /* VPNFlowPrivate.h in Headers */,
                                1572C4C30CFB55B400E2776E /* DeviceOnHold.h in Headers */,
                                1572C4C50CFB55B400E2776E /* dy_framework.h in Headers */,
                                1572C4C70CFB55B400E2776E /* SCPreferencesPathKey.h in Headers */,
                                1572C4CA0CFB55B400E2776E /* pppcontroller_types.h in Headers */,
-                               1572C4CB0CFB55B400E2776E /* pppcontroller.h in Headers */,
+                               1572C581171CD00E00870549 /* pppcontroller_mach_defines.h in Headers */,
                                1572C4CE0CFB55B400E2776E /* SCPreferencesSetSpecificPrivate.h in Headers */,
+                               C4CDB819163193AA00819B44 /* VPNFlow.h in Headers */,
                                1572C4CF0CFB55B400E2776E /* SCPreferencesGetSpecificPrivate.h in Headers */,
                                1572C4D00CFB55B400E2776E /* SCNetworkConfigurationPrivate.h in Headers */,
                                1572C4D20CFB55B400E2776E /* SCHelper_client.h in Headers */,
+                               B0A88CA816397A1200A60B3A /* VPNAppLayerPrivate.h in Headers */,
                                1572C4D40CFB55B400E2776E /* SCNetworkConnectionPrivate.h in Headers */,
                                1572C4D50CFB55B400E2776E /* SCPreferencesKeychainPrivate.h in Headers */,
                                1572C4D60CFB55B400E2776E /* SCSchemaDefinitionsPrivate.h in Headers */,
                                1572C4D70CFB55B400E2776E /* SCNetworkSignature.h in Headers */,
+                               B0C9689E174426DD00889853 /* SNHelperPrivate.h in Headers */,
                                1572C4D80CFB55B400E2776E /* SCNetworkSignaturePrivate.h in Headers */,
                                15A1FF3210597F17004C9CC9 /* CaptiveNetwork.h in Headers */,
                                159A751A107FEAA400A57EAB /* VPNPrivate.h in Headers */,
                                159A751C107FEAA400A57EAB /* VPNConfiguration.h in Headers */,
                                15AAA7F5108E310700C2A607 /* VPNTunnel.h in Headers */,
                                15AAA7F4108E310700C2A607 /* VPNTunnelPrivate.h in Headers */,
-                               15C330C5134B92780028E36B /* rb.h in Headers */,
                                15C330D2134B95AA0028E36B /* SCNetworkReachabilityInternal.h in Headers */,
                                15D8B22B1450D8450090CECF /* SCD.h in Headers */,
+                               B084711016385121006C92A3 /* SCNetworkConnectionInternal.h in Headers */,
+                               1572C4CB0CFB55B400E2776E /* pppcontroller.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
-               157433DE0D4A8122002ACA73 /* Headers */ = {
+               15732A7716EA503200F3AC4C /* Headers */ = {
                        isa = PBXHeadersBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
+                               15732A7816EA503200F3AC4C /* configd.h in Headers */,
+                               15732A7916EA503200F3AC4C /* _SCD.h in Headers */,
+                               15732A7A16EA503200F3AC4C /* configd_server.h in Headers */,
+                               15732A7B16EA503200F3AC4C /* notify_server.h in Headers */,
+                               15732A7C16EA503200F3AC4C /* plugin_support.h in Headers */,
+                               15732A7D16EA503200F3AC4C /* session.h in Headers */,
+                               15732A7E16EA503200F3AC4C /* pattern.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
-               157433F10D4A8137002ACA73 /* Headers */ = {
+               15732AAE16EA511900F3AC4C /* Headers */ = {
                        isa = PBXHeadersBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
-                               157433F20D4A8137002ACA73 /* scutil.h in Headers */,
-                               157433F30D4A8137002ACA73 /* commands.h in Headers */,
-                               157433F40D4A8137002ACA73 /* dictionary.h in Headers */,
-                               157433F50D4A8137002ACA73 /* session.h in Headers */,
-                               157433F60D4A8137002ACA73 /* cache.h in Headers */,
-                               157433F70D4A8137002ACA73 /* notifications.h in Headers */,
-                               157433F80D4A8137002ACA73 /* tests.h in Headers */,
-                               157433F90D4A8137002ACA73 /* prefs.h in Headers */,
-                               157433FA0D4A8137002ACA73 /* net.h in Headers */,
-                               157433FB0D4A8137002ACA73 /* net_interface.h in Headers */,
+                               15732AAF16EA511900F3AC4C /* scutil.h in Headers */,
+                               15732AB016EA511900F3AC4C /* commands.h in Headers */,
+                               15732AB116EA511900F3AC4C /* dictionary.h in Headers */,
+                               15732AB216EA511900F3AC4C /* session.h in Headers */,
+                               15732AB316EA511900F3AC4C /* cache.h in Headers */,
+                               15732AB416EA511900F3AC4C /* notifications.h in Headers */,
+                               15732AB516EA511900F3AC4C /* tests.h in Headers */,
+                               15732AB616EA511900F3AC4C /* prefs.h in Headers */,
+                               15732AB716EA511900F3AC4C /* net.h in Headers */,
+                               15732AB816EA511900F3AC4C /* net_interface.h in Headers */,
+                               15732AB916EA511900F3AC4C /* net_protocol.h in Headers */,
+                               15732ABA16EA511900F3AC4C /* net_service.h in Headers */,
+                               15732ABB16EA511900F3AC4C /* net_set.h in Headers */,
+                               15732ABC16EA511900F3AC4C /* nc.h in Headers */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               15732AD716EA6B6700F3AC4C /* Headers */ = {
+                       isa = PBXHeadersBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               15732AD816EA6B6700F3AC4C /* dnsinfo.h in Headers */,
+                               15732AD916EA6B6700F3AC4C /* network_information.h in Headers */,
+                               15732ADA16EA6B6700F3AC4C /* dnsinfo_private.h in Headers */,
+                               15732ADB16EA6B6700F3AC4C /* libSystemConfiguration_client.h in Headers */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               157433DE0D4A8122002ACA73 /* Headers */ = {
+                       isa = PBXHeadersBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               157433F10D4A8137002ACA73 /* Headers */ = {
+                       isa = PBXHeadersBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               157433F20D4A8137002ACA73 /* scutil.h in Headers */,
+                               157433F30D4A8137002ACA73 /* commands.h in Headers */,
+                               157433F40D4A8137002ACA73 /* dictionary.h in Headers */,
+                               157433F50D4A8137002ACA73 /* session.h in Headers */,
+                               157433F60D4A8137002ACA73 /* cache.h in Headers */,
+                               157433F70D4A8137002ACA73 /* notifications.h in Headers */,
+                               157433F80D4A8137002ACA73 /* tests.h in Headers */,
+                               157433F90D4A8137002ACA73 /* prefs.h in Headers */,
+                               157433FA0D4A8137002ACA73 /* net.h in Headers */,
+                               157433FB0D4A8137002ACA73 /* net_interface.h in Headers */,
                                157433FC0D4A8137002ACA73 /* net_protocol.h in Headers */,
                                157433FD0D4A8137002ACA73 /* net_service.h in Headers */,
                                157433FE0D4A8137002ACA73 /* net_set.h in Headers */,
                                157A84DA0D56C63900B6F1A0 /* dnsinfo.h in Headers */,
                                D661C2F21368BB720030B977 /* network_information.h in Headers */,
                                157A84DB0D56C63900B6F1A0 /* dnsinfo_private.h in Headers */,
+                               153338C014BE7978004FCE22 /* libSystemConfiguration_client.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                E4F211D4137B0ABD00BBB915 /* network_information_priv.h in Headers */,
                                1575FD2812CD15C60003D86E /* proxy-configuration.h in Headers */,
                                157A84F70D56C7E800B6F1A0 /* set-hostname.h in Headers */,
+                               153ACCAC14E322D5005029A5 /* network_information_server.h in Headers */,
+                               1596A7B514EDB73D00798C39 /* libSystemConfiguration_server.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
-               1583EA05108395BB00A3BC0C /* Headers */ = {
-                       isa = PBXHeadersBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               1583EA06108395BB00A3BC0C /* dnsinfo.h in Headers */,
-                               151E0CA31378EE1000C5DA2A /* network_information.h in Headers */,
-                               1583EA07108395BB00A3BC0C /* dnsinfo_private.h in Headers */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               1583EA1A108395BB00A3BC0C /* Headers */ = {
-                       isa = PBXHeadersBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               1583EA1B108395BB00A3BC0C /* SCSchemaDefinitions.h in Headers */,
-                               1583EA1C108395BB00A3BC0C /* SystemConfiguration.h in Headers */,
-                               1583EA1D108395BB00A3BC0C /* SCPrivate.h in Headers */,
-                               1583EA1E108395BB00A3BC0C /* SCDPlugin.h in Headers */,
-                               1583EA1F108395BB00A3BC0C /* SCDynamicStoreInternal.h in Headers */,
-                               1583EA20108395BB00A3BC0C /* SCDynamicStore.h in Headers */,
-                               1583EA21108395BB00A3BC0C /* SCDynamicStorePrivate.h in Headers */,
-                               1583EA22108395BB00A3BC0C /* SCDynamicStoreKey.h in Headers */,
-                               1583EA23108395BB00A3BC0C /* SCDynamicStoreCopySpecific.h in Headers */,
-                               1583EA24108395BB00A3BC0C /* SCDynamicStoreCopySpecificPrivate.h in Headers */,
-                               1583EA25108395BB00A3BC0C /* SCDynamicStoreSetSpecificPrivate.h in Headers */,
-                               1583EA26108395BB00A3BC0C /* SCPreferencesInternal.h in Headers */,
-                               1583EA27108395BB00A3BC0C /* SCPreferences.h in Headers */,
-                               1583EA28108395BB00A3BC0C /* SCPreferencesPrivate.h in Headers */,
-                               1583EA29108395BB00A3BC0C /* SCPreferencesPath.h in Headers */,
-                               1583EA2A108395BB00A3BC0C /* SCPreferencesSetSpecific.h in Headers */,
-                               1583EA2B108395BB00A3BC0C /* SCNetworkConfiguration.h in Headers */,
-                               1583EA2C108395BB00A3BC0C /* SCNetworkConfigurationInternal.h in Headers */,
-                               1583EA2D108395BB00A3BC0C /* SCNetwork.h in Headers */,
-                               1583EA2E108395BB00A3BC0C /* SCNetworkConnection.h in Headers */,
-                               1583EA2F108395BB00A3BC0C /* SCNetworkReachability.h in Headers */,
-                               1583EA30108395BB00A3BC0C /* SCValidation.h in Headers */,
-                               1583EA31108395BB00A3BC0C /* DHCPClientPreferences.h in Headers */,
-                               1583EA32108395BB00A3BC0C /* SCDynamicStoreCopyDHCPInfo.h in Headers */,
-                               1583EA33108395BB00A3BC0C /* moh_msg.h in Headers */,
-                               1583EA34108395BB00A3BC0C /* moh.h in Headers */,
-                               1583EA35108395BB00A3BC0C /* DeviceOnHold.h in Headers */,
-                               1583EA36108395BB00A3BC0C /* dy_framework.h in Headers */,
-                               1583EA37108395BB00A3BC0C /* SCPreferencesPathKey.h in Headers */,
-                               1583EA38108395BB00A3BC0C /* pppcontroller_types.h in Headers */,
-                               1583EA39108395BB00A3BC0C /* pppcontroller.h in Headers */,
-                               1583EA3A108395BB00A3BC0C /* SCPreferencesSetSpecificPrivate.h in Headers */,
-                               1583EA3B108395BB00A3BC0C /* SCPreferencesGetSpecificPrivate.h in Headers */,
-                               1583EA3C108395BB00A3BC0C /* SCNetworkConfigurationPrivate.h in Headers */,
-                               1583EA3E108395BB00A3BC0C /* SCHelper_client.h in Headers */,
-                               1583EA3F108395BB00A3BC0C /* SCNetworkConnectionPrivate.h in Headers */,
-                               1583EA40108395BB00A3BC0C /* SCPreferencesKeychainPrivate.h in Headers */,
-                               1583EA41108395BB00A3BC0C /* SCSchemaDefinitionsPrivate.h in Headers */,
-                               1583EA42108395BB00A3BC0C /* SCNetworkSignature.h in Headers */,
-                               1583EA43108395BB00A3BC0C /* SCNetworkSignaturePrivate.h in Headers */,
-                               1583EA44108395BB00A3BC0C /* CaptiveNetwork.h in Headers */,
-                               15C330C7134B92780028E36B /* rb.h in Headers */,
-                               15C330D4134B95AA0028E36B /* SCNetworkReachabilityInternal.h in Headers */,
-                               15D8B22D1450D8450090CECF /* SCD.h in Headers */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               1583EA9C108395BB00A3BC0C /* Headers */ = {
-                       isa = PBXHeadersBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               1583EA9E108395BB00A3BC0C /* SCHelper_client.h in Headers */,
-                               152E0E8B10FE824000E402F2 /* helper_types.h in Headers */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               1583EACB108395BB00A3BC0C /* Headers */ = {
-                       isa = PBXHeadersBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               1583EACC108395BB00A3BC0C /* dns-configuration.h in Headers */,
-                               1583EACE108395BB00A3BC0C /* dnsinfo_create.h in Headers */,
-                               E4F211D6137B0ADB00BBB915 /* network_information_priv.h in Headers */,
-                               1575FD2C12CD15C60003D86E /* proxy-configuration.h in Headers */,
-                               1583EACD108395BB00A3BC0C /* set-hostname.h in Headers */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               1583EAE1108395BB00A3BC0C /* Headers */ = {
-                       isa = PBXHeadersBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               1583EAF0108395BC00A3BC0C /* Headers */ = {
-                       isa = PBXHeadersBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               1583EAF1108395BC00A3BC0C /* cache.h in Headers */,
-                               1583EAF2108395BC00A3BC0C /* ev_dlil.h in Headers */,
-                               1583EAF3108395BC00A3BC0C /* ev_ipv4.h in Headers */,
-                               1583EAF4108395BC00A3BC0C /* ev_ipv6.h in Headers */,
-                               1583EAF5108395BC00A3BC0C /* eventmon.h in Headers */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               1583EB08108395BC00A3BC0C /* Headers */ = {
-                       isa = PBXHeadersBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               1583EB33108395BD00A3BC0C /* Headers */ = {
-                       isa = PBXHeadersBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               1583EB4C108395BD00A3BC0C /* Headers */ = {
-                       isa = PBXHeadersBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               1583EB4D108395BD00A3BC0C /* configd.h in Headers */,
-                               1583EB4E108395BD00A3BC0C /* _SCD.h in Headers */,
-                               1583EB4F108395BD00A3BC0C /* configd_server.h in Headers */,
-                               1583EB50108395BD00A3BC0C /* notify_server.h in Headers */,
-                               1583EB51108395BD00A3BC0C /* plugin_support.h in Headers */,
-                               1583EB52108395BD00A3BC0C /* session.h in Headers */,
-                               1583EB53108395BD00A3BC0C /* pattern.h in Headers */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               1583EB87108395BE00A3BC0C /* Headers */ = {
-                       isa = PBXHeadersBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               1583EB93108395BE00A3BC0C /* Headers */ = {
-                       isa = PBXHeadersBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               1583EB94108395BE00A3BC0C /* scutil.h in Headers */,
-                               1583EB95108395BE00A3BC0C /* commands.h in Headers */,
-                               1583EB96108395BE00A3BC0C /* dictionary.h in Headers */,
-                               1583EB97108395BE00A3BC0C /* session.h in Headers */,
-                               1583EB98108395BE00A3BC0C /* cache.h in Headers */,
-                               1583EB99108395BE00A3BC0C /* notifications.h in Headers */,
-                               1583EB9A108395BE00A3BC0C /* tests.h in Headers */,
-                               1583EB9B108395BE00A3BC0C /* prefs.h in Headers */,
-                               1583EB9C108395BE00A3BC0C /* net.h in Headers */,
-                               1583EB9D108395BE00A3BC0C /* net_interface.h in Headers */,
-                               1583EB9E108395BE00A3BC0C /* net_protocol.h in Headers */,
-                               1583EB9F108395BE00A3BC0C /* net_service.h in Headers */,
-                               1583EBA0108395BE00A3BC0C /* net_set.h in Headers */,
-                               15B274A6114467D8003414AD /* nc.h in Headers */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
                159D53D007528BDA004F8947 /* Headers */ = {
                        isa = PBXHeadersBuildPhase;
                        buildActionMask = 2147483647;
                                1575FD2A12CD15C60003D86E /* proxy-configuration.h in Headers */,
                                155D223C0AF13A7300D52ED0 /* set-hostname.h in Headers */,
                                155D223D0AF13A7300D52ED0 /* smb-configuration.h in Headers */,
+                               153ACCAB14E322D5005029A5 /* network_information_server.h in Headers */,
+                               1596A7B414EDB73D00798C39 /* libSystemConfiguration_server.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                15A5A1FB0D5B94190087BDA0 /* SCNetworkReachability.h in Headers */,
                                15A5A1FC0D5B94190087BDA0 /* SCValidation.h in Headers */,
                                15A5A1FD0D5B94190087BDA0 /* DHCPClientPreferences.h in Headers */,
+                               D61AAEB71522C9EF0066B003 /* scprefs_observer.h in Headers */,
                                15A5A1FE0D5B94190087BDA0 /* SCDynamicStoreCopyDHCPInfo.h in Headers */,
                                15A5A1FF0D5B94190087BDA0 /* moh_msg.h in Headers */,
                                15A5A2000D5B94190087BDA0 /* moh.h in Headers */,
                                15A5A2060D5B94190087BDA0 /* dnsinfo.h in Headers */,
                                15A5A2070D5B94190087BDA0 /* dnsinfo_private.h in Headers */,
                                15A5A2080D5B94190087BDA0 /* pppcontroller_types.h in Headers */,
-                               15A5A2090D5B94190087BDA0 /* pppcontroller.h in Headers */,
+                               1572C57F171CCFE200870549 /* pppcontroller_mach_defines.h in Headers */,
                                15A5A20C0D5B94190087BDA0 /* SCPreferencesSetSpecificPrivate.h in Headers */,
                                15A5A20D0D5B94190087BDA0 /* SCPreferencesGetSpecificPrivate.h in Headers */,
                                15A5A20E0D5B94190087BDA0 /* SCNetworkConfigurationPrivate.h in Headers */,
                                15A1FF3410597F17004C9CC9 /* CaptiveNetwork.h in Headers */,
                                159A7528107FEAA400A57EAB /* VPNPrivate.h in Headers */,
                                159A752A107FEAA400A57EAB /* VPNConfiguration.h in Headers */,
-                               15C330C6134B92780028E36B /* rb.h in Headers */,
                                15C330D3134B95AA0028E36B /* SCNetworkReachabilityInternal.h in Headers */,
                                15D8B22C1450D8450090CECF /* SCD.h in Headers */,
+                               15A5A2090D5B94190087BDA0 /* pppcontroller.h in Headers */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               15AB751316EBFF3400FAA8CE /* Headers */ = {
+                       isa = PBXHeadersBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               15D3081016F3E4DA00014F82 /* Headers */ = {
+                       isa = PBXHeadersBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               15C8C6C0170AAB4E005375CE /* cache.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                15DAD5E1075913CE0084A6ED /* dnsinfo.h in Headers */,
                                D661C2EF1368BB280030B977 /* network_information.h in Headers */,
                                15DAD5E2075913CE0084A6ED /* dnsinfo_private.h in Headers */,
+                               153338BF14BE7978004FCE22 /* libSystemConfiguration_client.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                15DAD65007591A1A0084A6ED /* SCPreferencesPath.h in Headers */,
                                15DAD65107591A1A0084A6ED /* SCPreferencesSetSpecific.h in Headers */,
                                15DAD65207591A1A0084A6ED /* SCNetworkConfiguration.h in Headers */,
+                               D61AAEB51522C9D00066B003 /* scprefs_observer.h in Headers */,
                                15DAD65307591A1A0084A6ED /* SCNetworkConfigurationInternal.h in Headers */,
                                15DAD65407591A1A0084A6ED /* SCNetwork.h in Headers */,
                                15DAD65507591A1A0084A6ED /* SCNetworkConnection.h in Headers */,
                                15DAD65A07591A1A0084A6ED /* moh_msg.h in Headers */,
                                15DAD65B07591A1A0084A6ED /* moh.h in Headers */,
                                15DAD65C07591A1A0084A6ED /* DeviceOnHold.h in Headers */,
-                               15DAD65D07591A1A0084A6ED /* LinkConfiguration.h in Headers */,
+                               C4CDB8181631938400819B44 /* VPNFlowPrivate.h in Headers */,
                                15DAD65E07591A1A0084A6ED /* dy_framework.h in Headers */,
                                15DAD66107591A1A0084A6ED /* SCPreferencesPathKey.h in Headers */,
                                15DAD66407591A1A0084A6ED /* pppcontroller_types.h in Headers */,
-                               15DAD66507591A1A0084A6ED /* pppcontroller.h in Headers */,
+                               1572C580171CCFF000870549 /* pppcontroller_mach_defines.h in Headers */,
+                               B0A88CA716397A1200A60B3A /* VPNAppLayerPrivate.h in Headers */,
                                156BD6BC07E0DFA9008698FF /* SCPreferencesSetSpecificPrivate.h in Headers */,
                                154CF3F407E1EA4D00D8302E /* SCPreferencesGetSpecificPrivate.h in Headers */,
+                               C4CDB8171631938000819B44 /* VPNFlow.h in Headers */,
                                155A1E6C081079CC00F70D98 /* SCNetworkConfigurationPrivate.h in Headers */,
                                155B7BF80847776D00F0E262 /* SCHelper_client.h in Headers */,
                                15D8B22A1450D8450090CECF /* SCD.h in Headers */,
                                15A297300A13C08C009879B3 /* SCNetworkConnectionPrivate.h in Headers */,
                                152E68C10A2C89C70011FDA8 /* SCPreferencesKeychainPrivate.h in Headers */,
+                               B0C967F817441F0E00889853 /* SNHelperPrivate.h in Headers */,
                                157A88890A470D0F003A4256 /* SCSchemaDefinitionsPrivate.h in Headers */,
                                F95B8A460B03E09300993BA3 /* SCNetworkSignature.h in Headers */,
                                F95B8A470B03E09300993BA3 /* SCNetworkSignaturePrivate.h in Headers */,
                                159A7523107FEAA400A57EAB /* VPNConfiguration.h in Headers */,
                                15AAA7F8108E310700C2A607 /* VPNTunnel.h in Headers */,
                                15AAA7F7108E310700C2A607 /* VPNTunnelPrivate.h in Headers */,
-                               15C330C4134B92780028E36B /* rb.h in Headers */,
                                15C330D1134B95AA0028E36B /* SCNetworkReachabilityInternal.h in Headers */,
+                               B084710F16385121006C92A3 /* SCNetworkConnectionInternal.h in Headers */,
+                               15DAD66507591A1A0084A6ED /* pppcontroller.h in Headers */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               15E1B04216EBAE3C00E5F06F /* Headers */ = {
+                       isa = PBXHeadersBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               15E1B04316EBAE3C00E5F06F /* dns-configuration.h in Headers */,
+                               15E1B04416EBAE3C00E5F06F /* dnsinfo_create.h in Headers */,
+                               15E1B04516EBAE3C00E5F06F /* network_information_priv.h in Headers */,
+                               15E1B04616EBAE3C00E5F06F /* proxy-configuration.h in Headers */,
+                               15E1B04816EBAE3C00E5F06F /* network_information_server.h in Headers */,
+                               15E1B04916EBAE3C00E5F06F /* libSystemConfiguration_server.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        productReference = 1528BFFE13573FF500691881 /* SCNetworkReachability.bundle */;
                        productType = "com.apple.product-type.bundle";
                };
-               1528BFFF1357401900691881 /* SCNetworkReachability-EmbeddedOther */ = {
-                       isa = PBXNativeTarget;
-                       buildConfigurationList = 1528C0031357401900691881 /* Build configuration list for PBXNativeTarget "SCNetworkReachability-EmbeddedOther" */;
-                       buildPhases = (
-                               1528C0001357401900691881 /* Headers */,
-                               1528C0011357401900691881 /* Sources */,
-                       );
-                       buildRules = (
-                       );
-                       dependencies = (
-                       );
-                       name = "SCNetworkReachability-EmbeddedOther";
-                       productName = PreferencesMonitor;
-                       productReference = 1528C0061357401900691881 /* libSCNetworkReachability.a */;
-                       productType = "com.apple.product-type.library.static";
-               };
-               1528C0071357401D00691881 /* SCNetworkReachability.bundle-EmbeddedOther */ = {
-                       isa = PBXNativeTarget;
-                       buildConfigurationList = 1528C00A1357401D00691881 /* Build configuration list for PBXNativeTarget "SCNetworkReachability.bundle-EmbeddedOther" */;
-                       buildPhases = (
-                               1528C0081357401D00691881 /* Resources */,
-                       );
-                       buildRules = (
-                       );
-                       dependencies = (
-                       );
-                       name = "SCNetworkReachability.bundle-EmbeddedOther";
-                       productInstallPath = "$(USER_LIBRARY_DIR)/Bundles";
-                       productName = PreferencesMonitor.bundle;
-                       productReference = 1528C00D1357401D00691881 /* SCNetworkReachability.bundle */;
-                       productType = "com.apple.product-type.bundle";
-               };
                1547001808455B98006787CE /* SCHelper */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = 156EB5E20905594A00EEF749 /* Build configuration list for PBXNativeTarget "SCHelper" */;
                        productReference = 1547072E0D1F70C80075C28D /* SystemConfiguration.framework */;
                        productType = "com.apple.product-type.framework";
                };
+               15732A7616EA503200F3AC4C /* configd-EmbeddedSimulator */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = 15732AA916EA503200F3AC4C /* Build configuration list for PBXNativeTarget "configd-EmbeddedSimulator" */;
+                       buildPhases = (
+                               15732A7716EA503200F3AC4C /* Headers */,
+                               15732A7F16EA503200F3AC4C /* Sources */,
+                               15732A9B16EA503200F3AC4C /* Frameworks */,
+                               15732AA716EA503200F3AC4C /* CopyFiles */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               15AB752A16EC254D00FAA8CE /* PBXTargetDependency */,
+                               15AB752C16EC254D00FAA8CE /* PBXTargetDependency */,
+                               15D3083516F3EB2500014F82 /* PBXTargetDependency */,
+                       );
+                       name = "configd-EmbeddedSimulator";
+                       productInstallPath = /usr/sbin;
+                       productName = "configd (Tool)";
+                       productReference = 15732AAC16EA503300F3AC4C /* configd_sim */;
+                       productType = "com.apple.product-type.tool";
+               };
+               15732AAD16EA511900F3AC4C /* scutil-EmbeddedSimulator */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = 15732AD216EA511900F3AC4C /* Build configuration list for PBXNativeTarget "scutil-EmbeddedSimulator" */;
+                       buildPhases = (
+                               15732AAE16EA511900F3AC4C /* Headers */,
+                               15732ABD16EA511900F3AC4C /* Sources */,
+                               15732ACD16EA511900F3AC4C /* Frameworks */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                       );
+                       name = "scutil-EmbeddedSimulator";
+                       productInstallPath = /usr/sbin;
+                       productName = "scutil (Tool)";
+                       productReference = 15732AD516EA511900F3AC4C /* scutil_sim */;
+                       productType = "com.apple.product-type.tool";
+               };
+               15732AD616EA6B6700F3AC4C /* libsystem_configuration-EmbeddedSimulator */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = 15732AE116EA6B6700F3AC4C /* Build configuration list for PBXNativeTarget "libsystem_configuration-EmbeddedSimulator" */;
+                       buildPhases = (
+                               15732AD716EA6B6700F3AC4C /* Headers */,
+                               15732ADC16EA6B6700F3AC4C /* Sources */,
+                               15732AE016EA6B6700F3AC4C /* Frameworks */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                       );
+                       name = "libsystem_configuration-EmbeddedSimulator";
+                       productInstallPath = /usr/local/lib/system;
+                       productName = DNSConfiguration;
+                       productReference = 15732AE416EA6B6700F3AC4C /* libsystem_sim_configuration.dylib */;
+                       productType = "com.apple.product-type.library.dynamic";
+               };
                157433DD0D4A8122002ACA73 /* scselect-Embedded */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = 157433E80D4A8122002ACA73 /* Build configuration list for PBXNativeTarget "scselect-Embedded" */;
                        productReference = 1574341A0D4A8137002ACA73 /* scutil */;
                        productType = "com.apple.product-type.tool";
                };
-               157A84D80D56C63900B6F1A0 /* DNSConfiguration-Embedded */ = {
+               157A84D80D56C63900B6F1A0 /* libsystem_configuration-Embedded */ = {
                        isa = PBXNativeTarget;
-                       buildConfigurationList = 157A84E40D56C63900B6F1A0 /* Build configuration list for PBXNativeTarget "DNSConfiguration-Embedded" */;
+                       buildConfigurationList = 157A84E40D56C63900B6F1A0 /* Build configuration list for PBXNativeTarget "libsystem_configuration-Embedded" */;
                        buildPhases = (
                                157A84D90D56C63900B6F1A0 /* Headers */,
                                157A84DD0D56C63900B6F1A0 /* Sources */,
                        );
                        dependencies = (
                        );
-                       name = "DNSConfiguration-Embedded";
+                       name = "libsystem_configuration-Embedded";
                        productInstallPath = /usr/local/lib/system;
                        productName = DNSConfiguration;
-                       productReference = 157A84E80D56C63900B6F1A0 /* libdnsinfo.dylib */;
+                       productReference = 157A84E80D56C63900B6F1A0 /* libsystem_configuration.dylib */;
                        productType = "com.apple.product-type.library.dynamic";
                };
                157A84F40D56C7E800B6F1A0 /* IPMonitor-Embedded */ = {
                        buildConfigurationList = 158317800CFB85C8006F62B9 /* Build configuration list for PBXNativeTarget "IPMonitor.bundle-Embedded" */;
                        buildPhases = (
                                1583177E0CFB85C8006F62B9 /* Resources */,
+                               15D54E2515B4FA1900F5229A /* com.apple.networking.IPMonitor */,
                        );
                        buildRules = (
                        );
                        productReference = 1559C4470D349A4E0098FD59 /* SCHelper */;
                        productType = "com.apple.product-type.tool";
                };
-               1583EA04108395BB00A3BC0C /* DNSConfiguration-EmbeddedOther */ = {
+               159D53D307528BDA004F8947 /* KernelEventMonitor */ = {
                        isa = PBXNativeTarget;
-                       buildConfigurationList = 1583EA0D108395BB00A3BC0C /* Build configuration list for PBXNativeTarget "DNSConfiguration-EmbeddedOther" */;
+                       buildConfigurationList = 156EB6020905594A00EEF749 /* Build configuration list for PBXNativeTarget "KernelEventMonitor" */;
                        buildPhases = (
-                               1583EA05108395BB00A3BC0C /* Headers */,
-                               1583EA08108395BB00A3BC0C /* Sources */,
-                               1583EA0C108395BB00A3BC0C /* Frameworks */,
+                               159D53D007528BDA004F8947 /* Headers */,
+                               159D53D107528BDA004F8947 /* Sources */,
                        );
                        buildRules = (
                        );
                        dependencies = (
                        );
-                       name = "DNSConfiguration-EmbeddedOther";
-                       productInstallPath = /usr/local/lib/system;
-                       productName = DNSConfiguration;
-                       productReference = 1583EA10108395BB00A3BC0C /* libdnsinfo.dylib */;
-                       productType = "com.apple.product-type.library.dynamic";
+                       name = KernelEventMonitor;
+                       productName = KernelEventMonitor;
+                       productReference = 159D53D407528BDA004F8947 /* libKernelEventMonitor.a */;
+                       productType = "com.apple.product-type.library.static";
                };
-               1583EA19108395BB00A3BC0C /* SystemConfiguration.framework-EmbeddedOther */ = {
+               159D53E407528C4A004F8947 /* InterfaceNamer */ = {
                        isa = PBXNativeTarget;
-                       buildConfigurationList = 1583EA96108395BB00A3BC0C /* Build configuration list for PBXNativeTarget "SystemConfiguration.framework-EmbeddedOther" */;
+                       buildConfigurationList = 156EB5F60905594A00EEF749 /* Build configuration list for PBXNativeTarget "InterfaceNamer" */;
                        buildPhases = (
-                               1583EA1A108395BB00A3BC0C /* Headers */,
-                               1583EA49108395BB00A3BC0C /* Update Headers */,
-                               1583EA4A108395BB00A3BC0C /* Resources */,
-                               1583EA4F108395BB00A3BC0C /* Sources */,
-                               1583EA93108395BB00A3BC0C /* Frameworks */,
-                               1583EA95108395BB00A3BC0C /* get-mobility-info */,
+                               159D53E107528C4A004F8947 /* Headers */,
+                               159D53E207528C4A004F8947 /* Sources */,
                        );
                        buildRules = (
                        );
                        dependencies = (
                        );
-                       name = "SystemConfiguration.framework-EmbeddedOther";
-                       productInstallPath = "$(SYSTEM_LIBRARY_DIR)/Frameworks";
-                       productName = "SystemConfiguration (Framework)";
-                       productReference = 1583EA99108395BB00A3BC0C /* SystemConfiguration.framework */;
-                       productType = "com.apple.product-type.framework";
+                       name = InterfaceNamer;
+                       productName = InterfaceNamer;
+                       productReference = 159D53E507528C4A004F8947 /* libInterfaceNamer.a */;
+                       productType = "com.apple.product-type.library.static";
                };
-               1583EA9B108395BB00A3BC0C /* SCHelper-EmbeddedOther */ = {
+               159D53EB07528C61004F8947 /* IPMonitor */ = {
                        isa = PBXNativeTarget;
-                       buildConfigurationList = 1583EAA7108395BB00A3BC0C /* Build configuration list for PBXNativeTarget "SCHelper-EmbeddedOther" */;
+                       buildConfigurationList = 156EB5EE0905594A00EEF749 /* Build configuration list for PBXNativeTarget "IPMonitor" */;
                        buildPhases = (
-                               1583EA9C108395BB00A3BC0C /* Headers */,
-                               1583EA9F108395BB00A3BC0C /* Sources */,
-                               1583EAA1108395BB00A3BC0C /* Frameworks */,
-                               1583EAA5108395BB00A3BC0C /* CopyFiles */,
+                               159D53E807528C61004F8947 /* Headers */,
+                               159D53E907528C61004F8947 /* Sources */,
                        );
                        buildRules = (
                        );
                        dependencies = (
                        );
-                       name = "SCHelper-EmbeddedOther";
-                       productInstallPath = /usr/local/bin;
-                       productName = SCPreferencesHelper;
-                       productReference = 1583EAAA108395BB00A3BC0C /* SCHelper */;
-                       productType = "com.apple.product-type.tool";
+                       name = IPMonitor;
+                       productName = IPMonitor;
+                       productReference = 159D53EC07528C61004F8947 /* libIPMonitor.a */;
+                       productType = "com.apple.product-type.library.static";
                };
-               1583EACA108395BB00A3BC0C /* IPMonitor-EmbeddedOther */ = {
+               159D53F207528C79004F8947 /* LinkConfiguration */ = {
                        isa = PBXNativeTarget;
-                       buildConfigurationList = 1583EAD5108395BB00A3BC0C /* Build configuration list for PBXNativeTarget "IPMonitor-EmbeddedOther" */;
+                       buildConfigurationList = 156EB60E0905594A00EEF749 /* Build configuration list for PBXNativeTarget "LinkConfiguration" */;
                        buildPhases = (
-                               1583EACB108395BB00A3BC0C /* Headers */,
-                               1583EACF108395BB00A3BC0C /* Sources */,
+                               159D53EF07528C79004F8947 /* Headers */,
+                               159D53F007528C79004F8947 /* Sources */,
                        );
                        buildRules = (
                        );
                        dependencies = (
                        );
-                       name = "IPMonitor-EmbeddedOther";
-                       productName = IPMonitor;
-                       productReference = 1583EAD8108395BB00A3BC0C /* libIPMonitor.a */;
+                       name = LinkConfiguration;
+                       productName = LinkConfiguration;
+                       productReference = 159D53F307528C79004F8947 /* libLinkConfiguration.a */;
                        productType = "com.apple.product-type.library.static";
                };
-               1583EAD9108395BB00A3BC0C /* IPMonitor.bundle-EmbeddedOther */ = {
+               159D53F907528C95004F8947 /* PreferencesMonitor */ = {
                        isa = PBXNativeTarget;
-                       buildConfigurationList = 1583EADB108395BB00A3BC0C /* Build configuration list for PBXNativeTarget "IPMonitor.bundle-EmbeddedOther" */;
+                       buildConfigurationList = 156EB6160905594A00EEF749 /* Build configuration list for PBXNativeTarget "PreferencesMonitor" */;
                        buildPhases = (
-                               1583EADA108395BB00A3BC0C /* Resources */,
+                               159D53F607528C95004F8947 /* Headers */,
+                               159D53F707528C95004F8947 /* Sources */,
                        );
                        buildRules = (
                        );
                        dependencies = (
                        );
-                       name = "IPMonitor.bundle-EmbeddedOther";
-                       productInstallPath = "$(USER_LIBRARY_DIR)/Bundles";
-                       productName = IPMonitor.bundle;
-                       productReference = 1583EADE108395BB00A3BC0C /* IPMonitor.bundle */;
-                       productType = "com.apple.product-type.bundle";
+                       name = PreferencesMonitor;
+                       productName = PreferencesMonitor;
+                       productReference = 159D53FA07528C95004F8947 /* libPreferencesMonitor.a */;
+                       productType = "com.apple.product-type.library.static";
                };
-               1583EAE0108395BB00A3BC0C /* InterfaceNamer-EmbeddedOther */ = {
+               159D549F07529FFF004F8947 /* configd */ = {
                        isa = PBXNativeTarget;
-                       buildConfigurationList = 1583EAE4108395BB00A3BC0C /* Build configuration list for PBXNativeTarget "InterfaceNamer-EmbeddedOther" */;
+                       buildConfigurationList = 156EB6220905594A00EEF749 /* Build configuration list for PBXNativeTarget "configd" */;
                        buildPhases = (
-                               1583EAE1108395BB00A3BC0C /* Headers */,
-                               1583EAE2108395BB00A3BC0C /* Sources */,
+                               159D54A307529FFF004F8947 /* Headers */,
+                               159D54AB07529FFF004F8947 /* Sources */,
+                               159D54CA07529FFF004F8947 /* Frameworks */,
+                               159D54D507529FFF004F8947 /* CopyFiles */,
+                               159D54D707529FFF004F8947 /* CopyFiles */,
                        );
                        buildRules = (
                        );
                        dependencies = (
                        );
-                       name = "InterfaceNamer-EmbeddedOther";
-                       productName = InterfaceNamer;
-                       productReference = 1583EAE7108395BB00A3BC0C /* libInterfaceNamer.a */;
-                       productType = "com.apple.product-type.library.static";
+                       name = configd;
+                       productInstallPath = /usr/sbin;
+                       productName = "configd (Tool)";
+                       productReference = 159D54D907529FFF004F8947 /* configd */;
+                       productType = "com.apple.product-type.tool";
                };
-               1583EAE8108395BC00A3BC0C /* InterfaceNamer.bundle-EmbeddedOther */ = {
+               15A5A1E40D5B94190087BDA0 /* SystemConfiguration.framework-EmbeddedSimulator */ = {
                        isa = PBXNativeTarget;
-                       buildConfigurationList = 1583EAEA108395BC00A3BC0C /* Build configuration list for PBXNativeTarget "InterfaceNamer.bundle-EmbeddedOther" */;
+                       buildConfigurationList = 15A5A2660D5B94190087BDA0 /* Build configuration list for PBXNativeTarget "SystemConfiguration.framework-EmbeddedSimulator" */;
                        buildPhases = (
-                               1583EAE9108395BC00A3BC0C /* Resources */,
+                               15A5A1E60D5B94190087BDA0 /* Headers */,
+                               15A5A2170D5B94190087BDA0 /* Update Headers */,
+                               15A5A2180D5B94190087BDA0 /* Resources */,
+                               15A5A21D0D5B94190087BDA0 /* Sources */,
+                               15A5A2620D5B94190087BDA0 /* Frameworks */,
                        );
                        buildRules = (
                        );
                        dependencies = (
                        );
-                       name = "InterfaceNamer.bundle-EmbeddedOther";
-                       productInstallPath = "$(USER_LIBRARY_DIR)/Bundles";
-                       productName = InterfaceNamer.bundle;
-                       productReference = 1583EAED108395BC00A3BC0C /* InterfaceNamer.bundle */;
-                       productType = "com.apple.product-type.bundle";
+                       name = "SystemConfiguration.framework-EmbeddedSimulator";
+                       productInstallPath = "$(SYSTEM_LIBRARY_DIR)/Frameworks";
+                       productName = "SystemConfiguration (Framework)";
+                       productReference = 15A5A26A0D5B94190087BDA0 /* SystemConfiguration.framework */;
+                       productType = "com.apple.product-type.framework";
                };
-               1583EAEF108395BC00A3BC0C /* KernelEventMonitor-EmbeddedOther */ = {
+               15AB751216EBFF3400FAA8CE /* SCNetworkReachability-EmbeddedSimulator */ = {
                        isa = PBXNativeTarget;
-                       buildConfigurationList = 1583EAFC108395BC00A3BC0C /* Build configuration list for PBXNativeTarget "KernelEventMonitor-EmbeddedOther" */;
+                       buildConfigurationList = 15AB751616EBFF3400FAA8CE /* Build configuration list for PBXNativeTarget "SCNetworkReachability-EmbeddedSimulator" */;
                        buildPhases = (
-                               1583EAF0108395BC00A3BC0C /* Headers */,
-                               1583EAF6108395BC00A3BC0C /* Sources */,
+                               15AB751316EBFF3400FAA8CE /* Headers */,
+                               15AB751416EBFF3400FAA8CE /* Sources */,
                        );
                        buildRules = (
                        );
                        dependencies = (
                        );
-                       name = "KernelEventMonitor-EmbeddedOther";
-                       productName = KernelEventMonitor;
-                       productReference = 1583EAFF108395BC00A3BC0C /* libKernelEventMonitor.a */;
+                       name = "SCNetworkReachability-EmbeddedSimulator";
+                       productName = PreferencesMonitor;
+                       productReference = 15AB751916EBFF3400FAA8CE /* libSCNetworkReachability_sim.a */;
                        productType = "com.apple.product-type.library.static";
                };
-               1583EB00108395BC00A3BC0C /* KernelEventMonitor.bundle-EmbeddedOther */ = {
+               15AB751A16EBFF8A00FAA8CE /* SCNetworkReachability.bundle-EmbeddedSimulator */ = {
                        isa = PBXNativeTarget;
-                       buildConfigurationList = 1583EB02108395BC00A3BC0C /* Build configuration list for PBXNativeTarget "KernelEventMonitor.bundle-EmbeddedOther" */;
+                       buildConfigurationList = 15AB751C16EBFF8A00FAA8CE /* Build configuration list for PBXNativeTarget "SCNetworkReachability.bundle-EmbeddedSimulator" */;
                        buildPhases = (
-                               1583EB01108395BC00A3BC0C /* Resources */,
+                               15AB751B16EBFF8A00FAA8CE /* Resources */,
                        );
                        buildRules = (
                        );
                        dependencies = (
                        );
-                       name = "KernelEventMonitor.bundle-EmbeddedOther";
-                       productName = KernelEventMonitor.bundle;
-                       productReference = 1583EB05108395BC00A3BC0C /* KernelEventMonitor.bundle */;
-                       productType = "com.apple.product-type.bundle";
-               };
-               1583EB07108395BC00A3BC0C /* LinkConfiguration-EmbeddedOther */ = {
-                       isa = PBXNativeTarget;
-                       buildConfigurationList = 1583EB0B108395BC00A3BC0C /* Build configuration list for PBXNativeTarget "LinkConfiguration-EmbeddedOther" */;
-                       buildPhases = (
-                               1583EB08108395BC00A3BC0C /* Headers */,
-                               1583EB09108395BC00A3BC0C /* Sources */,
-                       );
-                       buildRules = (
-                       );
-                       dependencies = (
-                       );
-                       name = "LinkConfiguration-EmbeddedOther";
-                       productName = LinkConfiguration;
-                       productReference = 1583EB0E108395BC00A3BC0C /* libLinkConfiguration.a */;
-                       productType = "com.apple.product-type.library.static";
-               };
-               1583EB0F108395BC00A3BC0C /* LinkConfiguration.bundle-EmbeddedOther */ = {
-                       isa = PBXNativeTarget;
-                       buildConfigurationList = 1583EB11108395BC00A3BC0C /* Build configuration list for PBXNativeTarget "LinkConfiguration.bundle-EmbeddedOther" */;
-                       buildPhases = (
-                               1583EB10108395BC00A3BC0C /* Resources */,
-                       );
-                       buildRules = (
-                       );
-                       dependencies = (
-                       );
-                       name = "LinkConfiguration.bundle-EmbeddedOther";
-                       productInstallPath = "$(USER_LIBRARY_DIR)/Bundles";
-                       productName = LinkConfiguration.bundle;
-                       productReference = 1583EB14108395BC00A3BC0C /* LinkConfiguration.bundle */;
-                       productType = "com.apple.product-type.bundle";
-               };
-               1583EB16108395BC00A3BC0C /* Logger.bundle-EmbeddedOther */ = {
-                       isa = PBXNativeTarget;
-                       buildConfigurationList = 1583EB1E108395BC00A3BC0C /* Build configuration list for PBXNativeTarget "Logger.bundle-EmbeddedOther" */;
-                       buildPhases = (
-                               1583EB17108395BC00A3BC0C /* Sources */,
-                               1583EB19108395BC00A3BC0C /* Frameworks */,
-                               1583EB1D108395BC00A3BC0C /* Resources */,
-                       );
-                       buildRules = (
-                       );
-                       dependencies = (
-                       );
-                       name = "Logger.bundle-EmbeddedOther";
-                       productName = Logger.bundle;
-                       productReference = 1583EB21108395BC00A3BC0C /* Logger.bundle */;
-                       productType = "com.apple.product-type.bundle";
-               };
-               1583EB32108395BD00A3BC0C /* PreferencesMonitor-EmbeddedOther */ = {
-                       isa = PBXNativeTarget;
-                       buildConfigurationList = 1583EB36108395BD00A3BC0C /* Build configuration list for PBXNativeTarget "PreferencesMonitor-EmbeddedOther" */;
-                       buildPhases = (
-                               1583EB33108395BD00A3BC0C /* Headers */,
-                               1583EB34108395BD00A3BC0C /* Sources */,
-                       );
-                       buildRules = (
-                       );
-                       dependencies = (
-                       );
-                       name = "PreferencesMonitor-EmbeddedOther";
-                       productName = PreferencesMonitor;
-                       productReference = 1583EB39108395BD00A3BC0C /* libPreferencesMonitor.a */;
-                       productType = "com.apple.product-type.library.static";
-               };
-               1583EB3A108395BD00A3BC0C /* PreferencesMonitor.bundle-EmbeddedOther */ = {
-                       isa = PBXNativeTarget;
-                       buildConfigurationList = 1583EB3C108395BD00A3BC0C /* Build configuration list for PBXNativeTarget "PreferencesMonitor.bundle-EmbeddedOther" */;
-                       buildPhases = (
-                               1583EB3B108395BD00A3BC0C /* Resources */,
-                       );
-                       buildRules = (
-                       );
-                       dependencies = (
-                       );
-                       name = "PreferencesMonitor.bundle-EmbeddedOther";
+                       name = "SCNetworkReachability.bundle-EmbeddedSimulator";
                        productInstallPath = "$(USER_LIBRARY_DIR)/Bundles";
                        productName = PreferencesMonitor.bundle;
-                       productReference = 1583EB3F108395BD00A3BC0C /* PreferencesMonitor.bundle */;
+                       productReference = 15AB751F16EBFF8A00FAA8CE /* SCNetworkReachability.bundle */;
                        productType = "com.apple.product-type.bundle";
                };
-               1583EB4B108395BD00A3BC0C /* configd-EmbeddedOther */ = {
-                       isa = PBXNativeTarget;
-                       buildConfigurationList = 1583EB81108395BD00A3BC0C /* Build configuration list for PBXNativeTarget "configd-EmbeddedOther" */;
-                       buildPhases = (
-                               1583EB4C108395BD00A3BC0C /* Headers */,
-                               1583EB54108395BD00A3BC0C /* Sources */,
-                               1583EB73108395BD00A3BC0C /* Frameworks */,
-                               1583EB7F108395BD00A3BC0C /* CopyFiles */,
-                       );
-                       buildRules = (
-                       );
-                       dependencies = (
-                       );
-                       name = "configd-EmbeddedOther";
-                       productInstallPath = /usr/sbin;
-                       productName = "configd (Tool)";
-                       productReference = 1583EB84108395BD00A3BC0C /* configd */;
-                       productType = "com.apple.product-type.tool";
-               };
-               1583EB86108395BE00A3BC0C /* scselect-EmbeddedOther */ = {
-                       isa = PBXNativeTarget;
-                       buildConfigurationList = 1583EB8D108395BE00A3BC0C /* Build configuration list for PBXNativeTarget "scselect-EmbeddedOther" */;
-                       buildPhases = (
-                               1583EB87108395BE00A3BC0C /* Headers */,
-                               1583EB88108395BE00A3BC0C /* Sources */,
-                               1583EB8A108395BE00A3BC0C /* Frameworks */,
-                       );
-                       buildRules = (
-                       );
-                       dependencies = (
-                       );
-                       name = "scselect-EmbeddedOther";
-                       productInstallPath = /usr/sbin;
-                       productName = "scselect (Tool)";
-                       productReference = 1583EB90108395BE00A3BC0C /* scselect */;
-                       productType = "com.apple.product-type.tool";
-               };
-               1583EB92108395BE00A3BC0C /* scutil-EmbeddedOther */ = {
-                       isa = PBXNativeTarget;
-                       buildConfigurationList = 1583EBB3108395BE00A3BC0C /* Build configuration list for PBXNativeTarget "scutil-EmbeddedOther" */;
-                       buildPhases = (
-                               1583EB93108395BE00A3BC0C /* Headers */,
-                               1583EBA1108395BE00A3BC0C /* Sources */,
-                               1583EBAF108395BE00A3BC0C /* Frameworks */,
-                       );
-                       buildRules = (
-                       );
-                       dependencies = (
-                       );
-                       name = "scutil-EmbeddedOther";
-                       productInstallPath = /usr/sbin;
-                       productName = "scutil (Tool)";
-                       productReference = 1583EBB6108395BE00A3BC0C /* scutil */;
-                       productType = "com.apple.product-type.tool";
-               };
-               159D53D307528BDA004F8947 /* KernelEventMonitor */ = {
-                       isa = PBXNativeTarget;
-                       buildConfigurationList = 156EB6020905594A00EEF749 /* Build configuration list for PBXNativeTarget "KernelEventMonitor" */;
-                       buildPhases = (
-                               159D53D007528BDA004F8947 /* Headers */,
-                               159D53D107528BDA004F8947 /* Sources */,
-                       );
-                       buildRules = (
-                       );
-                       dependencies = (
-                       );
-                       name = KernelEventMonitor;
-                       productName = KernelEventMonitor;
-                       productReference = 159D53D407528BDA004F8947 /* libKernelEventMonitor.a */;
-                       productType = "com.apple.product-type.library.static";
-               };
-               159D53E407528C4A004F8947 /* InterfaceNamer */ = {
-                       isa = PBXNativeTarget;
-                       buildConfigurationList = 156EB5F60905594A00EEF749 /* Build configuration list for PBXNativeTarget "InterfaceNamer" */;
-                       buildPhases = (
-                               159D53E107528C4A004F8947 /* Headers */,
-                               159D53E207528C4A004F8947 /* Sources */,
-                       );
-                       buildRules = (
-                       );
-                       dependencies = (
-                       );
-                       name = InterfaceNamer;
-                       productName = InterfaceNamer;
-                       productReference = 159D53E507528C4A004F8947 /* libInterfaceNamer.a */;
-                       productType = "com.apple.product-type.library.static";
-               };
-               159D53EB07528C61004F8947 /* IPMonitor */ = {
+               15D3080F16F3E4DA00014F82 /* SimulatorSupport-EmbeddedSimulator */ = {
                        isa = PBXNativeTarget;
-                       buildConfigurationList = 156EB5EE0905594A00EEF749 /* Build configuration list for PBXNativeTarget "IPMonitor" */;
+                       buildConfigurationList = 15D3082416F3E4DA00014F82 /* Build configuration list for PBXNativeTarget "SimulatorSupport-EmbeddedSimulator" */;
                        buildPhases = (
-                               159D53E807528C61004F8947 /* Headers */,
-                               159D53E907528C61004F8947 /* Sources */,
+                               15D3081016F3E4DA00014F82 /* Headers */,
+                               15D3081816F3E4DA00014F82 /* Sources */,
                        );
                        buildRules = (
                        );
                        dependencies = (
                        );
-                       name = IPMonitor;
+                       name = "SimulatorSupport-EmbeddedSimulator";
                        productName = IPMonitor;
-                       productReference = 159D53EC07528C61004F8947 /* libIPMonitor.a */;
-                       productType = "com.apple.product-type.library.static";
-               };
-               159D53F207528C79004F8947 /* LinkConfiguration */ = {
-                       isa = PBXNativeTarget;
-                       buildConfigurationList = 156EB60E0905594A00EEF749 /* Build configuration list for PBXNativeTarget "LinkConfiguration" */;
-                       buildPhases = (
-                               159D53EF07528C79004F8947 /* Headers */,
-                               159D53F007528C79004F8947 /* Sources */,
-                       );
-                       buildRules = (
-                       );
-                       dependencies = (
-                       );
-                       name = LinkConfiguration;
-                       productName = LinkConfiguration;
-                       productReference = 159D53F307528C79004F8947 /* libLinkConfiguration.a */;
-                       productType = "com.apple.product-type.library.static";
-               };
-               159D53F907528C95004F8947 /* PreferencesMonitor */ = {
-                       isa = PBXNativeTarget;
-                       buildConfigurationList = 156EB6160905594A00EEF749 /* Build configuration list for PBXNativeTarget "PreferencesMonitor" */;
-                       buildPhases = (
-                               159D53F607528C95004F8947 /* Headers */,
-                               159D53F707528C95004F8947 /* Sources */,
-                       );
-                       buildRules = (
-                       );
-                       dependencies = (
-                       );
-                       name = PreferencesMonitor;
-                       productName = PreferencesMonitor;
-                       productReference = 159D53FA07528C95004F8947 /* libPreferencesMonitor.a */;
+                       productReference = 15D3082716F3E4DA00014F82 /* libSimulatorSupport_sim.a */;
                        productType = "com.apple.product-type.library.static";
                };
-               159D549F07529FFF004F8947 /* configd */ = {
-                       isa = PBXNativeTarget;
-                       buildConfigurationList = 156EB6220905594A00EEF749 /* Build configuration list for PBXNativeTarget "configd" */;
-                       buildPhases = (
-                               159D54A307529FFF004F8947 /* Headers */,
-                               159D54AB07529FFF004F8947 /* Sources */,
-                               159D54CA07529FFF004F8947 /* Frameworks */,
-                               159D54D507529FFF004F8947 /* CopyFiles */,
-                               159D54D707529FFF004F8947 /* CopyFiles */,
-                       );
-                       buildRules = (
-                       );
-                       dependencies = (
-                       );
-                       name = configd;
-                       productInstallPath = /usr/sbin;
-                       productName = "configd (Tool)";
-                       productReference = 159D54D907529FFF004F8947 /* configd */;
-                       productType = "com.apple.product-type.tool";
-               };
-               15A5A1E40D5B94190087BDA0 /* SystemConfiguration.framework-EmbeddedSimulator */ = {
+               15D3082816F3E4E100014F82 /* SimulatorSupport.bundle-EmbeddedSimulator */ = {
                        isa = PBXNativeTarget;
-                       buildConfigurationList = 15A5A2660D5B94190087BDA0 /* Build configuration list for PBXNativeTarget "SystemConfiguration.framework-EmbeddedSimulator" */;
+                       buildConfigurationList = 15D3082A16F3E4E100014F82 /* Build configuration list for PBXNativeTarget "SimulatorSupport.bundle-EmbeddedSimulator" */;
                        buildPhases = (
-                               15A5A1E60D5B94190087BDA0 /* Headers */,
-                               15A5A2170D5B94190087BDA0 /* Update Headers */,
-                               15A5A2180D5B94190087BDA0 /* Resources */,
-                               15A5A21D0D5B94190087BDA0 /* Sources */,
-                               15A5A2620D5B94190087BDA0 /* Frameworks */,
+                               15D3082916F3E4E100014F82 /* Resources */,
                        );
                        buildRules = (
                        );
                        dependencies = (
                        );
-                       name = "SystemConfiguration.framework-EmbeddedSimulator";
-                       productInstallPath = "$(SYSTEM_LIBRARY_DIR)/Frameworks";
-                       productName = "SystemConfiguration (Framework)";
-                       productReference = 15A5A26A0D5B94190087BDA0 /* SystemConfiguration.framework */;
-                       productType = "com.apple.product-type.framework";
+                       name = "SimulatorSupport.bundle-EmbeddedSimulator";
+                       productInstallPath = "$(USER_LIBRARY_DIR)/Bundles";
+                       productName = IPMonitor.bundle;
+                       productReference = 15D3082D16F3E4E100014F82 /* SimulatorSupport.bundle */;
+                       productType = "com.apple.product-type.bundle";
                };
-               15DAD5DF075913CE0084A6ED /* DNSConfiguration */ = {
+               15DAD5DF075913CE0084A6ED /* libsystem_configuration */ = {
                        isa = PBXNativeTarget;
-                       buildConfigurationList = 156EB5DA0905594A00EEF749 /* Build configuration list for PBXNativeTarget "DNSConfiguration" */;
+                       buildConfigurationList = 156EB5DA0905594A00EEF749 /* Build configuration list for PBXNativeTarget "libsystem_configuration" */;
                        buildPhases = (
                                15DAD5E0075913CE0084A6ED /* Headers */,
                                15DAD5E4075913CE0084A6ED /* Sources */,
                        );
                        dependencies = (
                        );
-                       name = DNSConfiguration;
+                       name = libsystem_configuration;
                        productInstallPath = /usr/local/lib/system;
                        productName = DNSConfiguration;
-                       productReference = 15DAD5EE075913CE0084A6ED /* libdnsinfo.dylib */;
+                       productReference = 15DAD5EE075913CE0084A6ED /* libsystem_configuration.dylib */;
                        productType = "com.apple.product-type.library.dynamic";
                };
                15DAD63F07591A1A0084A6ED /* SystemConfiguration.framework */ = {
                                15DAD66C07591A1A0084A6ED /* Sources */,
                                15DAD6AD07591A1A0084A6ED /* Frameworks */,
                                15DAD6B007591A1A0084A6ED /* get-mobility-info */,
-                               15D9DCF910DD909F004E545D /* CopyFiles */,
+                               15D9DCF910DD909F004E545D /* AppWorkaround.plist */,
                        );
                        buildRules = (
                        );
                        productReference = 1559C4440D349A4E0098FD59 /* SystemConfiguration.framework */;
                        productType = "com.apple.product-type.framework";
                };
+               15E1B04116EBAE3C00E5F06F /* IPMonitor-EmbeddedSimulator */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = 15E1B05616EBAE3C00E5F06F /* Build configuration list for PBXNativeTarget "IPMonitor-EmbeddedSimulator" */;
+                       buildPhases = (
+                               15E1B04216EBAE3C00E5F06F /* Headers */,
+                               15E1B04A16EBAE3C00E5F06F /* Sources */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                       );
+                       name = "IPMonitor-EmbeddedSimulator";
+                       productName = IPMonitor;
+                       productReference = 15E1B05916EBAE3C00E5F06F /* libIPMonitor_sim.a */;
+                       productType = "com.apple.product-type.library.static";
+               };
+               15E1B05A16EBAE7800E5F06F /* IPMonitor.bundle-EmbeddedSimulator */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = 15E1B05E16EBAE7800E5F06F /* Build configuration list for PBXNativeTarget "IPMonitor.bundle-EmbeddedSimulator" */;
+                       buildPhases = (
+                               15E1B05B16EBAE7800E5F06F /* Resources */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                       );
+                       name = "IPMonitor.bundle-EmbeddedSimulator";
+                       productInstallPath = "$(USER_LIBRARY_DIR)/Bundles";
+                       productName = IPMonitor.bundle;
+                       productReference = 15E1B06116EBAE7800E5F06F /* IPMonitor.bundle */;
+                       productType = "com.apple.product-type.bundle";
+               };
                15FD72930754DA2B001CC321 /* InterfaceNamer.bundle */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = 156EB5FA0905594A00EEF749 /* Build configuration list for PBXNativeTarget "InterfaceNamer.bundle" */;
                        buildConfigurationList = 156EB5F20905594A00EEF749 /* Build configuration list for PBXNativeTarget "IPMonitor.bundle" */;
                        buildPhases = (
                                15FD72A20754DA4C001CC321 /* Resources */,
+                               15D54E2A15B4FAF100F5229A /* com.apple.networking.IPMonitor */,
                        );
                        buildRules = (
                        );
                15CB6A7705C0722B0099E85F /* Project object */ = {
                        isa = PBXProject;
                        attributes = {
-                               LastUpgradeCheck = 0430;
+                               LastUpgradeCheck = 0500;
                        };
                        buildConfigurationList = 156EB63E0905594A00EEF749 /* Build configuration list for PBXProject "configd" */;
                        compatibilityVersion = "Xcode 3.2";
                        targets = (
                                15CB690005C0722A0099E85F /* All */,
                                15C64A1E0F684C3300D78394 /* configd_libSystem */,
-                               15DAD5DF075913CE0084A6ED /* DNSConfiguration */,
+                               15DAD5DF075913CE0084A6ED /* libsystem_configuration */,
                                157BB8AE075924360025DA7A /* configd_base */,
                                15DAD63F07591A1A0084A6ED /* SystemConfiguration.framework */,
                                1547001808455B98006787CE /* SCHelper */,
                                151F5D990CCE98E50093AC3B /* SCMonitor */,
                                151C1CC60CFB487000C5AFD6 /* All-Embedded */,
                                15C64A280F684C6B00D78394 /* configd_libSystem-Embedded */,
-                               157A84D80D56C63900B6F1A0 /* DNSConfiguration-Embedded */,
+                               157A84D80D56C63900B6F1A0 /* libsystem_configuration-Embedded */,
                                158316CF0CFB774B006F62B9 /* configd_base-Embedded */,
                                1572C4A60CFB55B400E2776E /* SystemConfiguration.framework-Embedded */,
                                158337990CFB6B9E0033AB93 /* SCHelper-Embedded */,
                                157433DD0D4A8122002ACA73 /* scselect-Embedded */,
                                157433F00D4A8137002ACA73 /* scutil-Embedded */,
                                15FD13BF0D59485000F9409C /* All-EmbeddedSimulator */,
+                               157FDE3B164A075F0040D6A8 /* configd_libSystem-EmbeddedSimulator */,
+                               15732AD616EA6B6700F3AC4C /* libsystem_configuration-EmbeddedSimulator */,
                                151FE2DD0D5B7046000D6DB1 /* configd_base-EmbeddedSimulator */,
                                15A5A1E40D5B94190087BDA0 /* SystemConfiguration.framework-EmbeddedSimulator */,
+                               15E1B04116EBAE3C00E5F06F /* IPMonitor-EmbeddedSimulator */,
+                               15E1B05A16EBAE7800E5F06F /* IPMonitor.bundle-EmbeddedSimulator */,
+                               15AB751216EBFF3400FAA8CE /* SCNetworkReachability-EmbeddedSimulator */,
+                               15AB751A16EBFF8A00FAA8CE /* SCNetworkReachability.bundle-EmbeddedSimulator */,
+                               15D3080F16F3E4DA00014F82 /* SimulatorSupport-EmbeddedSimulator */,
+                               15D3082816F3E4E100014F82 /* SimulatorSupport.bundle-EmbeddedSimulator */,
+                               15732A7616EA503200F3AC4C /* configd-EmbeddedSimulator */,
+                               15732AAD16EA511900F3AC4C /* scutil-EmbeddedSimulator */,
                                151F63DA09328A3C0096DCC9 /* Schema */,
-                               1583E9E01083959E00A3BC0C /* All-EmbeddedOther */,
-                               1583E9FD108395BB00A3BC0C /* configd_libSystem-EmbeddedOther */,
-                               1583EA04108395BB00A3BC0C /* DNSConfiguration-EmbeddedOther */,
-                               1583EA11108395BB00A3BC0C /* configd_base-EmbeddedOther */,
-                               1583EA19108395BB00A3BC0C /* SystemConfiguration.framework-EmbeddedOther */,
-                               1583EA9B108395BB00A3BC0C /* SCHelper-EmbeddedOther */,
-                               1583EAAC108395BB00A3BC0C /* configd_plugins-EmbeddedOther */,
-                               1583EACA108395BB00A3BC0C /* IPMonitor-EmbeddedOther */,
-                               1583EAD9108395BB00A3BC0C /* IPMonitor.bundle-EmbeddedOther */,
-                               1583EAE0108395BB00A3BC0C /* InterfaceNamer-EmbeddedOther */,
-                               1583EAE8108395BC00A3BC0C /* InterfaceNamer.bundle-EmbeddedOther */,
-                               1583EAEF108395BC00A3BC0C /* KernelEventMonitor-EmbeddedOther */,
-                               1583EB00108395BC00A3BC0C /* KernelEventMonitor.bundle-EmbeddedOther */,
-                               1583EB07108395BC00A3BC0C /* LinkConfiguration-EmbeddedOther */,
-                               1583EB0F108395BC00A3BC0C /* LinkConfiguration.bundle-EmbeddedOther */,
-                               1583EB16108395BC00A3BC0C /* Logger.bundle-EmbeddedOther */,
-                               1583EB32108395BD00A3BC0C /* PreferencesMonitor-EmbeddedOther */,
-                               1583EB3A108395BD00A3BC0C /* PreferencesMonitor.bundle-EmbeddedOther */,
-                               1528BFFF1357401900691881 /* SCNetworkReachability-EmbeddedOther */,
-                               1528C0071357401D00691881 /* SCNetworkReachability.bundle-EmbeddedOther */,
-                               1583EB41108395BD00A3BC0C /* configd_executables-EmbeddedOther */,
-                               1583EB4B108395BD00A3BC0C /* configd-EmbeddedOther */,
-                               1583EB86108395BE00A3BC0C /* scselect-EmbeddedOther */,
-                               1583EB92108395BE00A3BC0C /* scutil-EmbeddedOther */,
+                               15E83104167F9AF600FD51EC /* EVERYTHING */,
                        );
                };
 /* End PBXProject section */
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
-               1528C0081357401D00691881 /* Resources */ = {
-                       isa = PBXResourcesBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
                156CA4810EF853BB00C59A18 /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
-               1583EA4A108395BB00A3BC0C /* Resources */ = {
+               15A5A2180D5B94190087BDA0 /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
-                               1583EA4B108395BB00A3BC0C /* Localizable.strings in Resources */,
-                               1583EA4C108395BB00A3BC0C /* NetworkInterface.strings in Resources */,
-                               1583EA4D108395BB00A3BC0C /* NetworkConfiguration.plist in Resources */,
-                               1583EA4E108395BB00A3BC0C /* get-mobility-info in Resources */,
+                               15A5A2190D5B94190087BDA0 /* Localizable.strings in Resources */,
+                               15A5A21A0D5B94190087BDA0 /* NetworkInterface.strings in Resources */,
+                               15A5A21B0D5B94190087BDA0 /* NetworkConfiguration.plist in Resources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
-               1583EADA108395BB00A3BC0C /* Resources */ = {
+               15AB751B16EBFF8A00FAA8CE /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
-               1583EAE9108395BC00A3BC0C /* Resources */ = {
+               15D3082916F3E4E100014F82 /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
-               1583EB01108395BC00A3BC0C /* Resources */ = {
+               15DAD66807591A1A0084A6ED /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
+                               15A6F7C40A4B266D00B907EA /* Localizable.strings in Resources */,
+                               15DAD66B07591A1A0084A6ED /* NetworkInterface.strings in Resources */,
+                               15DAD66907591A1A0084A6ED /* NetworkConfiguration.plist in Resources */,
+                               15DAD66A07591A1A0084A6ED /* get-mobility-info in Resources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
-               1583EB10108395BC00A3BC0C /* Resources */ = {
+               15E1B05B16EBAE7800E5F06F /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
-               1583EB1D108395BC00A3BC0C /* Resources */ = {
+               15FD72940754DA2B001CC321 /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
-               1583EB3B108395BD00A3BC0C /* Resources */ = {
+               15FD72A20754DA4C001CC321 /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
-               15A5A2180D5B94190087BDA0 /* Resources */ = {
+               15FD72B20754DA69001CC321 /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
-                               15A5A2190D5B94190087BDA0 /* Localizable.strings in Resources */,
-                               15A5A21A0D5B94190087BDA0 /* NetworkInterface.strings in Resources */,
-                               15A5A21B0D5B94190087BDA0 /* NetworkConfiguration.plist in Resources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
-               15DAD66807591A1A0084A6ED /* Resources */ = {
+               15FD72C60754DA7E001CC321 /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
-                               15A6F7C40A4B266D00B907EA /* Localizable.strings in Resources */,
-                               15DAD66B07591A1A0084A6ED /* NetworkInterface.strings in Resources */,
-                               15DAD66907591A1A0084A6ED /* NetworkConfiguration.plist in Resources */,
-                               15DAD66A07591A1A0084A6ED /* get-mobility-info in Resources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
-               15FD72940754DA2B001CC321 /* Resources */ = {
-                       isa = PBXResourcesBuildPhase;
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+               151F63DB09328A3C0096DCC9 /* ShellScript */ = {
+                       isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
                        );
+                       inputPaths = (
+                               SystemConfiguration.fproj/genSCPreferences.c,
+                       );
+                       outputPaths = (
+                               "${BUILT_PRODUCTS_DIR}/SCSchemaDefinitions.h",
+                               "${BUILT_PRODUCTS_DIR}/SCSchemaDefinitionsPrivate.h",
+                               "${BUILT_PRODUCTS_DIR}/SCSchemaDefinitions.c",
+                       );
                        runOnlyForDeploymentPostprocessing = 0;
-               };
-               15FD72A20754DA4C001CC321 /* Resources */ = {
-                       isa = PBXResourcesBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               15FD72B20754DA69001CC321 /* Resources */ = {
-                       isa = PBXResourcesBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               15FD72C60754DA7E001CC321 /* Resources */ = {
-                       isa = PBXResourcesBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-/* End PBXResourcesBuildPhase section */
-
-/* Begin PBXShellScriptBuildPhase section */
-               151F63DB09328A3C0096DCC9 /* ShellScript */ = {
-                       isa = PBXShellScriptBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                       );
-                       inputPaths = (
-                               SystemConfiguration.fproj/genSCPreferences.c,
-                       );
-                       outputPaths = (
-                               "${BUILT_PRODUCTS_DIR}/SCSchemaDefinitions.h",
-                               "${BUILT_PRODUCTS_DIR}/SCSchemaDefinitionsPrivate.h",
-                               "${BUILT_PRODUCTS_DIR}/SCSchemaDefinitions.c",
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-                       shellPath = /bin/sh;
-                       shellScript = "echo ${BUILT_PRODUCTS_DIR}\ncc -o ${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME} ${SRCROOT}/SystemConfiguration.fproj/genSCPreferences.c || exit 1\n${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME} header   > ${BUILT_PRODUCTS_DIR}/SCSchemaDefinitions.h        || exit 1\n${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME} private  > ${BUILT_PRODUCTS_DIR}/SCSchemaDefinitionsPrivate.h || exit 1\n${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME} cfile    > ${BUILT_PRODUCTS_DIR}/SCSchemaDefinitions.c        || exit 1\nexit 0";
+                       shellPath = /bin/sh;
+                       shellScript = "echo ${BUILT_PRODUCTS_DIR}\ncc -o ${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME} ${SRCROOT}/SystemConfiguration.fproj/genSCPreferences.c || exit 1\n${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME} header   > ${BUILT_PRODUCTS_DIR}/SCSchemaDefinitions.h        || exit 1\n${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME} private  > ${BUILT_PRODUCTS_DIR}/SCSchemaDefinitionsPrivate.h || exit 1\n${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME} cfile    > ${BUILT_PRODUCTS_DIR}/SCSchemaDefinitions.c        || exit 1\nexit 0";
                };
                153393E40D34999D00FE74E7 /* Update Headers */ = {
                        isa = PBXShellScriptBuildPhase;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                        shellPath = /bin/sh;
-                       shellScript = "if [ -x ${SCRIPT_INPUT_FILE_0} ]; then\n\t${SCRIPT_INPUT_FILE_0} split\nfi\n";
+                       shellScript = "if [ -x ${SCRIPT_INPUT_FILE_0} ]; then\n\t${SCRIPT_INPUT_FILE_0} split\nfi";
                };
                1572C5270CFB55B400E2776E /* get-mobility-info */ = {
                        isa = PBXShellScriptBuildPhase;
                        shellScript = "mkdir -p \"${DSTROOT}/usr/local/bin\"\nln -fs \"${INSTALL_PATH}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/get-mobility-info\" \"${DSTROOT}/usr/local/bin/\"\n";
                        showEnvVarsInLog = 0;
                };
-               1583EA49108395BB00A3BC0C /* Update Headers */ = {
-                       isa = PBXShellScriptBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                       );
-                       inputPaths = (
-                               "$(SRCROOT)/SystemConfiguration.fproj/update-headers",
-                       );
-                       name = "Update Headers";
-                       outputPaths = (
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-                       shellPath = /bin/sh;
-                       shellScript = "if [ -x ${SCRIPT_INPUT_FILE_0} ]; then\n\t${SCRIPT_INPUT_FILE_0} split\nfi\n";
-               };
-               1583EA95108395BB00A3BC0C /* get-mobility-info */ = {
-                       isa = PBXShellScriptBuildPhase;
-                       buildActionMask = 8;
-                       files = (
-                       );
-                       inputPaths = (
-                       );
-                       name = "get-mobility-info";
-                       outputPaths = (
-                       );
-                       runOnlyForDeploymentPostprocessing = 1;
-                       shellPath = /bin/sh;
-                       shellScript = "mkdir -p \"${DSTROOT}/usr/local/bin\"\nln -fs \"${INSTALL_PATH}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/get-mobility-info\" \"${DSTROOT}/usr/local/bin/\"\n";
-                       showEnvVarsInLog = 0;
-               };
                15A5A2170D5B94190087BDA0 /* Update Headers */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                        shellPath = /bin/sh;
-                       shellScript = "if [ -x ${SCRIPT_INPUT_FILE_0} ]; then\n\t${SCRIPT_INPUT_FILE_0} split\nfi\n";
+                       shellScript = "if [ -x ${SCRIPT_INPUT_FILE_0} ]; then\n\t${SCRIPT_INPUT_FILE_0} split\nfi";
                        showEnvVarsInLog = 0;
                };
                15AC82480D376E2400A579D0 /* Update Headers */ = {
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
-               1528C0011357401900691881 /* Sources */ = {
-                       isa = PBXSourcesBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               1528C0021357401900691881 /* SCNetworkReachabilityServer_server.c in Sources */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
                1547001A08455B98006787CE /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                                155847600754FDCD0046C2E9 /* net_service.c in Sources */,
                                155847610754FDCD0046C2E9 /* net_set.c in Sources */,
                                72B43729113C7BFC00EBF1B6 /* nc.c in Sources */,
+                               F9B50FF316A4CBB200CA274E /* IPMonitorControlPrefs.c in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
+                               1572C5140CFB55B400E2776E /* config.defs in Sources */,
                                1572C4DF0CFB55B400E2776E /* SCSchemaDefinitions.c in Sources */,
                                1572C4E00CFB55B400E2776E /* SCD.c in Sources */,
                                1572C4E10CFB55B400E2776E /* SCDKeys.c in Sources */,
                                1572C4F90CFB55B400E2776E /* SCP.c in Sources */,
                                1572C4FA0CFB55B400E2776E /* SCPOpen.c in Sources */,
                                1572C4FB0CFB55B400E2776E /* SCPLock.c in Sources */,
+                               B0C9689D174426D100889853 /* SNHelper.c in Sources */,
                                1572C4FC0CFB55B400E2776E /* SCPUnlock.c in Sources */,
                                1572C4FD0CFB55B400E2776E /* SCPList.c in Sources */,
                                1572C4FE0CFB55B400E2776E /* SCPGet.c in Sources */,
                                1572C5000CFB55B400E2776E /* SCPSet.c in Sources */,
                                1572C5010CFB55B400E2776E /* SCPRemove.c in Sources */,
                                1572C5020CFB55B400E2776E /* SCPCommit.c in Sources */,
-                               1572C5030CFB55B400E2776E /* SCPApply.c in Sources */,
                                1572C5040CFB55B400E2776E /* SCPPath.c in Sources */,
+                               1572C5030CFB55B400E2776E /* SCPApply.c in Sources */,
                                1572C5060CFB55B400E2776E /* SCDHostName.c in Sources */,
                                1572C5070CFB55B400E2776E /* SCLocation.c in Sources */,
                                1572C5080CFB55B400E2776E /* SCNetwork.c in Sources */,
                                1572C5100CFB55B400E2776E /* DeviceOnHold.c in Sources */,
                                1572C5110CFB55B400E2776E /* LinkConfiguration.c in Sources */,
                                1572C5120CFB55B400E2776E /* dy_framework.c in Sources */,
-                               1572C5140CFB55B400E2776E /* config.defs in Sources */,
                                1572C5150CFB55B400E2776E /* SCPreferencesPathKey.c in Sources */,
-                               1572C5180CFB55B400E2776E /* shared_dns_info.defs in Sources */,
                                1572C5190CFB55B400E2776E /* SCNetworkConfigurationInternal.c in Sources */,
                                1572C51A0CFB55B400E2776E /* SCNetworkInterface.c in Sources */,
                                1572C51B0CFB55B400E2776E /* SCNetworkProtocol.c in Sources */,
                                152691DB1129EEA6006BD2D5 /* BridgeConfiguration.c in Sources */,
                                152691DE1129EEC2006BD2D5 /* VLANConfiguration.c in Sources */,
                                15C330BD134B92780028E36B /* SCNetworkReachabilityServer_client.c in Sources */,
-                               15C330C1134B92780028E36B /* rb.c in Sources */,
+                               D61AAEB01522C99C0066B003 /* scprefs_observer.c in Sources */,
+                               C4F1848116237AFC00D97043 /* VPNService.c in Sources */,
+                               C4CDB8161631935700819B44 /* VPNFlow.c in Sources */,
+                               B03FEFB716376D2800A1B88F /* VPNAppLayer.c in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               15732A7F16EA503200F3AC4C /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               15732A8016EA503200F3AC4C /* configd.m in Sources */,
+                               15732A8116EA503200F3AC4C /* _SCD.c in Sources */,
+                               15732A8216EA503200F3AC4C /* configd_server.c in Sources */,
+                               15732A8316EA503200F3AC4C /* notify_server.c in Sources */,
+                               15732A8416EA503200F3AC4C /* plugin_support.c in Sources */,
+                               15732A8516EA503200F3AC4C /* session.c in Sources */,
+                               15732A8616EA503200F3AC4C /* pattern.c in Sources */,
+                               15732A8716EA503200F3AC4C /* _configopen.c in Sources */,
+                               15732A8816EA503200F3AC4C /* _configclose.c in Sources */,
+                               15732A8916EA503200F3AC4C /* _configunlock.c in Sources */,
+                               15732A8A16EA503200F3AC4C /* _configlist.c in Sources */,
+                               15732A8B16EA503200F3AC4C /* _configadd.c in Sources */,
+                               15732A8C16EA503200F3AC4C /* _configget.c in Sources */,
+                               15732A8D16EA503200F3AC4C /* _configset.c in Sources */,
+                               15732A8E16EA503200F3AC4C /* _configremove.c in Sources */,
+                               15732A8F16EA503200F3AC4C /* _confignotify.c in Sources */,
+                               15732A9016EA503200F3AC4C /* _notifyadd.c in Sources */,
+                               15732A9116EA503200F3AC4C /* _notifyremove.c in Sources */,
+                               15732A9216EA503200F3AC4C /* _notifychanges.c in Sources */,
+                               15732A9316EA503200F3AC4C /* _notifyviaport.c in Sources */,
+                               15732A9416EA503200F3AC4C /* _notifyviafd.c in Sources */,
+                               15732A9516EA503200F3AC4C /* _notifyviasignal.c in Sources */,
+                               15732A9616EA503200F3AC4C /* _notifycancel.c in Sources */,
+                               15732A9716EA503200F3AC4C /* _snapshot.c in Sources */,
+                               15732A9816EA503200F3AC4C /* config.defs in Sources */,
+                               15732A9916EA503200F3AC4C /* dnsinfo_server.c in Sources */,
+                               15732A9A16EA503200F3AC4C /* SCNetworkReachabilityServer_server.c in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               15732ABD16EA511900F3AC4C /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               15732ABE16EA511900F3AC4C /* scutil.c in Sources */,
+                               15732ABF16EA511900F3AC4C /* commands.c in Sources */,
+                               15732AC016EA511900F3AC4C /* dictionary.c in Sources */,
+                               15732AC116EA511900F3AC4C /* session.c in Sources */,
+                               15732AC216EA511900F3AC4C /* cache.c in Sources */,
+                               15732AC316EA511900F3AC4C /* notifications.c in Sources */,
+                               15732AC416EA511900F3AC4C /* tests.c in Sources */,
+                               15732AC516EA511900F3AC4C /* prefs.c in Sources */,
+                               15732AC616EA511900F3AC4C /* net.c in Sources */,
+                               15732AC716EA511900F3AC4C /* net_interface.c in Sources */,
+                               15732AC816EA511900F3AC4C /* net_protocol.c in Sources */,
+                               15732AC916EA511900F3AC4C /* net_service.c in Sources */,
+                               15732ACA16EA511900F3AC4C /* net_set.c in Sources */,
+                               15732ACB16EA511900F3AC4C /* nc.c in Sources */,
+                               15732ACC16EA511900F3AC4C /* IPMonitorControlPrefs.c in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               15732ADC16EA6B6700F3AC4C /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               15732ADD16EA6B6700F3AC4C /* dnsinfo_copy.c in Sources */,
+                               15732ADE16EA6B6700F3AC4C /* network_information.c in Sources */,
+                               15732ADF16EA6B6700F3AC4C /* libSystemConfiguration_client.c in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                1574340B0D4A8137002ACA73 /* net_service.c in Sources */,
                                1574340C0D4A8137002ACA73 /* net_set.c in Sources */,
                                72B4372B113C7BFC00EBF1B6 /* nc.c in Sources */,
+                               F9B50FF416A4CBB800CA274E /* IPMonitorControlPrefs.c in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
-                               157A84DE0D56C63900B6F1A0 /* shared_dns_info.defs in Sources */,
                                157A84DF0D56C63900B6F1A0 /* dnsinfo_copy.c in Sources */,
-                               157A84E00D56C63900B6F1A0 /* dnsinfo_private.c in Sources */,
                                D661C2F11368BB600030B977 /* network_information.c in Sources */,
+                               153338BD14BE7978004FCE22 /* libSystemConfiguration_client.c in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        files = (
                                157A84FB0D56C7E800B6F1A0 /* dns-configuration.c in Sources */,
                                15D48EC10F67061F00B4711E /* dnsinfo_create.c in Sources */,
+                               150BEC1A14CA252200237116 /* dnsinfo_server.c in Sources */,
                                155281020E3E4A0F00C54315 /* ip_plugin.c in Sources */,
                                E4F211D3137B0AB900BBB915 /* network_information_priv.c in Sources */,
+                               153ACCA914E322D5005029A5 /* network_information_server.c in Sources */,
                                1575FD2712CD15C60003D86E /* proxy-configuration.c in Sources */,
                                157A84FC0D56C7E800B6F1A0 /* set-hostname.c in Sources */,
-                               15D48ED40F6707A600B4711E /* shared_dns_info.defs in Sources */,
+                               1596A7B214EDB73D00798C39 /* libSystemConfiguration_server.c in Sources */,
+                               D61AAEB11522C99C0066B003 /* scprefs_observer.c in Sources */,
+                               F9A3781116A4849100C57CDC /* IPMonitorControlPrefs.c in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                158317450CFB80A1006F62B9 /* _notifycancel.c in Sources */,
                                158317460CFB80A1006F62B9 /* _snapshot.c in Sources */,
                                158317470CFB80A1006F62B9 /* config.defs in Sources */,
-                               158317480CFB80A1006F62B9 /* dnsinfo_private.c in Sources */,
                                158317490CFB80A1006F62B9 /* dnsinfo_server.c in Sources */,
-                               1583174A0CFB80A1006F62B9 /* shared_dns_info.defs in Sources */,
                                15C330E5134BD2AC0028E36B /* SCNetworkReachabilityServer_server.c in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
-               1583EA08108395BB00A3BC0C /* Sources */ = {
-                       isa = PBXSourcesBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               1583EA09108395BB00A3BC0C /* shared_dns_info.defs in Sources */,
-                               1583EA0A108395BB00A3BC0C /* dnsinfo_copy.c in Sources */,
-                               1583EA0B108395BB00A3BC0C /* dnsinfo_private.c in Sources */,
-                               151E0CA51378EE3B00C5DA2A /* network_information.c in Sources */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               1583EA4F108395BB00A3BC0C /* Sources */ = {
-                       isa = PBXSourcesBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               1583EA50108395BB00A3BC0C /* SCSchemaDefinitions.c in Sources */,
-                               1583EA51108395BB00A3BC0C /* SCD.c in Sources */,
-                               1583EA52108395BB00A3BC0C /* SCDKeys.c in Sources */,
-                               1583EA53108395BB00A3BC0C /* SCDPrivate.c in Sources */,
-                               1583EA54108395BB00A3BC0C /* SCDPlugin.c in Sources */,
-                               1583EA55108395BB00A3BC0C /* SCDOpen.c in Sources */,
-                               1583EA58108395BB00A3BC0C /* SCDList.c in Sources */,
-                               1583EA59108395BB00A3BC0C /* SCDAdd.c in Sources */,
-                               1583EA5A108395BB00A3BC0C /* SCDGet.c in Sources */,
-                               1583EA5B108395BB00A3BC0C /* SCDSet.c in Sources */,
-                               1583EA5C108395BB00A3BC0C /* SCDRemove.c in Sources */,
-                               1583EA5E108395BB00A3BC0C /* SCDNotify.c in Sources */,
-                               1583EA5F108395BB00A3BC0C /* SCDNotifierSetKeys.c in Sources */,
-                               1583EA60108395BB00A3BC0C /* SCDNotifierAdd.c in Sources */,
-                               1583EA61108395BB00A3BC0C /* SCDNotifierRemove.c in Sources */,
-                               1583EA62108395BB00A3BC0C /* SCDNotifierGetChanges.c in Sources */,
-                               1583EA63108395BB00A3BC0C /* SCDNotifierWait.c in Sources */,
-                               1583EA64108395BB00A3BC0C /* SCDNotifierInformViaCallback.c in Sources */,
-                               1583EA66108395BB00A3BC0C /* SCDNotifierInformViaFD.c in Sources */,
-                               1583EA67108395BB00A3BC0C /* SCDNotifierInformViaSignal.c in Sources */,
-                               1583EA68108395BB00A3BC0C /* SCDNotifierCancel.c in Sources */,
-                               1583EA69108395BB00A3BC0C /* SCDSnapshot.c in Sources */,
-                               1583EA6A108395BB00A3BC0C /* SCP.c in Sources */,
-                               1583EA6B108395BB00A3BC0C /* SCPOpen.c in Sources */,
-                               1583EA6C108395BB00A3BC0C /* SCPLock.c in Sources */,
-                               1583EA6D108395BB00A3BC0C /* SCPUnlock.c in Sources */,
-                               1583EA6E108395BB00A3BC0C /* SCPList.c in Sources */,
-                               1583EA6F108395BB00A3BC0C /* SCPGet.c in Sources */,
-                               1583EA70108395BB00A3BC0C /* SCPAdd.c in Sources */,
-                               1583EA71108395BB00A3BC0C /* SCPSet.c in Sources */,
-                               1583EA72108395BB00A3BC0C /* SCPRemove.c in Sources */,
-                               1583EA73108395BB00A3BC0C /* SCPCommit.c in Sources */,
-                               1583EA74108395BB00A3BC0C /* SCPApply.c in Sources */,
-                               1583EA75108395BB00A3BC0C /* SCPPath.c in Sources */,
-                               1583EA76108395BB00A3BC0C /* SCDHostName.c in Sources */,
-                               1583EA77108395BB00A3BC0C /* SCLocation.c in Sources */,
-                               1583EA78108395BB00A3BC0C /* SCNetwork.c in Sources */,
-                               1583EA79108395BB00A3BC0C /* pppcontroller.defs in Sources */,
-                               1583EA7A108395BB00A3BC0C /* SCNetworkConnection.c in Sources */,
-                               1583EA7B108395BB00A3BC0C /* SCNetworkConnectionPrivate.c in Sources */,
-                               1583EA7C108395BB00A3BC0C /* SCNetworkReachability.c in Sources */,
-                               1583EA7D108395BB00A3BC0C /* SCProxies.c in Sources */,
-                               1583EA7E108395BB00A3BC0C /* DHCP.c in Sources */,
-                               1583EA7F108395BB00A3BC0C /* moh.c in Sources */,
-                               1583EA80108395BB00A3BC0C /* DeviceOnHold.c in Sources */,
-                               1583EA81108395BB00A3BC0C /* LinkConfiguration.c in Sources */,
-                               1583EA82108395BB00A3BC0C /* dy_framework.c in Sources */,
-                               1583EA83108395BB00A3BC0C /* config.defs in Sources */,
-                               1583EA84108395BB00A3BC0C /* SCPreferencesPathKey.c in Sources */,
-                               1583EA85108395BB00A3BC0C /* shared_dns_info.defs in Sources */,
-                               1583EA86108395BB00A3BC0C /* SCNetworkConfigurationInternal.c in Sources */,
-                               1583EA87108395BB00A3BC0C /* SCNetworkInterface.c in Sources */,
-                               1583EA88108395BB00A3BC0C /* SCNetworkProtocol.c in Sources */,
-                               1583EA89108395BB00A3BC0C /* SCNetworkService.c in Sources */,
-                               1583EA8A108395BB00A3BC0C /* SCNetworkSet.c in Sources */,
-                               1583EA8C108395BB00A3BC0C /* SCHelper_client.c in Sources */,
-                               1583EA8D108395BB00A3BC0C /* SCPreferencesKeychainPrivate.c in Sources */,
-                               1583EA8E108395BB00A3BC0C /* SCNetworkSignature.c in Sources */,
-                               1583EA8F108395BB00A3BC0C /* CaptiveNetwork.c in Sources */,
-                               158E59601107CAF10062081E /* helper.defs in Sources */,
-                               152691DD1129EEB1006BD2D5 /* BridgeConfiguration.c in Sources */,
-                               152691E01129EECB006BD2D5 /* VLANConfiguration.c in Sources */,
-                               15C330BF134B92780028E36B /* SCNetworkReachabilityServer_client.c in Sources */,
-                               15C330C3134B92780028E36B /* rb.c in Sources */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               1583EA9F108395BB00A3BC0C /* Sources */ = {
-                       isa = PBXSourcesBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               1583EAA0108395BB00A3BC0C /* SCHelper_server.c in Sources */,
-                               152E0E8110FE820E00E402F2 /* helper.defs in Sources */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               1583EACF108395BB00A3BC0C /* Sources */ = {
-                       isa = PBXSourcesBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               1583EAD1108395BB00A3BC0C /* dns-configuration.c in Sources */,
-                               1583EAD3108395BB00A3BC0C /* dnsinfo_create.c in Sources */,
-                               1583EAD0108395BB00A3BC0C /* ip_plugin.c in Sources */,
-                               E4F211D5137B0AD700BBB915 /* network_information_priv.c in Sources */,
-                               1575FD2B12CD15C60003D86E /* proxy-configuration.c in Sources */,
-                               1583EAD2108395BB00A3BC0C /* set-hostname.c in Sources */,
-                               1583EAD4108395BB00A3BC0C /* shared_dns_info.defs in Sources */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               1583EAE2108395BB00A3BC0C /* Sources */ = {
-                       isa = PBXSourcesBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               1583EAE3108395BB00A3BC0C /* ifnamer.c in Sources */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               1583EAF6108395BC00A3BC0C /* Sources */ = {
-                       isa = PBXSourcesBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               1583EAF7108395BC00A3BC0C /* cache.c in Sources */,
-                               1583EAF8108395BC00A3BC0C /* ev_dlil.c in Sources */,
-                               1583EAF9108395BC00A3BC0C /* ev_ipv4.c in Sources */,
-                               1583EAFA108395BC00A3BC0C /* ev_ipv6.c in Sources */,
-                               1583EAFB108395BC00A3BC0C /* eventmon.c in Sources */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               1583EB09108395BC00A3BC0C /* Sources */ = {
-                       isa = PBXSourcesBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               1583EB0A108395BC00A3BC0C /* linkconfig.c in Sources */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               1583EB17108395BC00A3BC0C /* Sources */ = {
-                       isa = PBXSourcesBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               1583EB18108395BC00A3BC0C /* logger.c in Sources */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               1583EB34108395BD00A3BC0C /* Sources */ = {
-                       isa = PBXSourcesBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               1583EB35108395BD00A3BC0C /* prefsmon.c in Sources */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               1583EB54108395BD00A3BC0C /* Sources */ = {
-                       isa = PBXSourcesBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               1583EB55108395BD00A3BC0C /* configd.m in Sources */,
-                               1583EB56108395BD00A3BC0C /* _SCD.c in Sources */,
-                               1583EB57108395BD00A3BC0C /* configd_server.c in Sources */,
-                               1583EB58108395BD00A3BC0C /* notify_server.c in Sources */,
-                               1583EB59108395BD00A3BC0C /* plugin_support.c in Sources */,
-                               1583EB5A108395BD00A3BC0C /* session.c in Sources */,
-                               1583EB5B108395BD00A3BC0C /* pattern.c in Sources */,
-                               1583EB5C108395BD00A3BC0C /* _configopen.c in Sources */,
-                               1583EB5D108395BD00A3BC0C /* _configclose.c in Sources */,
-                               1583EB5F108395BD00A3BC0C /* _configunlock.c in Sources */,
-                               1583EB60108395BD00A3BC0C /* _configlist.c in Sources */,
-                               1583EB61108395BD00A3BC0C /* _configadd.c in Sources */,
-                               1583EB62108395BD00A3BC0C /* _configget.c in Sources */,
-                               1583EB63108395BD00A3BC0C /* _configset.c in Sources */,
-                               1583EB64108395BD00A3BC0C /* _configremove.c in Sources */,
-                               1583EB66108395BD00A3BC0C /* _confignotify.c in Sources */,
-                               1583EB67108395BD00A3BC0C /* _notifyadd.c in Sources */,
-                               1583EB68108395BD00A3BC0C /* _notifyremove.c in Sources */,
-                               1583EB69108395BD00A3BC0C /* _notifychanges.c in Sources */,
-                               1583EB6A108395BD00A3BC0C /* _notifyviaport.c in Sources */,
-                               1583EB6B108395BD00A3BC0C /* _notifyviafd.c in Sources */,
-                               1583EB6C108395BD00A3BC0C /* _notifyviasignal.c in Sources */,
-                               1583EB6D108395BD00A3BC0C /* _notifycancel.c in Sources */,
-                               1583EB6E108395BD00A3BC0C /* _snapshot.c in Sources */,
-                               1583EB6F108395BD00A3BC0C /* config.defs in Sources */,
-                               1583EB70108395BD00A3BC0C /* dnsinfo_private.c in Sources */,
-                               1583EB71108395BD00A3BC0C /* dnsinfo_server.c in Sources */,
-                               1583EB72108395BD00A3BC0C /* shared_dns_info.defs in Sources */,
-                               15C330E6134BD2BB0028E36B /* SCNetworkReachabilityServer_server.c in Sources */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               1583EB88108395BE00A3BC0C /* Sources */ = {
-                       isa = PBXSourcesBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               1583EB89108395BE00A3BC0C /* scselect.c in Sources */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               1583EBA1108395BE00A3BC0C /* Sources */ = {
-                       isa = PBXSourcesBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               1583EBA2108395BE00A3BC0C /* scutil.c in Sources */,
-                               1583EBA3108395BE00A3BC0C /* commands.c in Sources */,
-                               1583EBA4108395BE00A3BC0C /* dictionary.c in Sources */,
-                               1583EBA5108395BE00A3BC0C /* session.c in Sources */,
-                               1583EBA6108395BE00A3BC0C /* cache.c in Sources */,
-                               1583EBA7108395BE00A3BC0C /* notifications.c in Sources */,
-                               1583EBA8108395BE00A3BC0C /* tests.c in Sources */,
-                               1583EBA9108395BE00A3BC0C /* prefs.c in Sources */,
-                               1583EBAA108395BE00A3BC0C /* net.c in Sources */,
-                               1583EBAB108395BE00A3BC0C /* net_interface.c in Sources */,
-                               1583EBAC108395BE00A3BC0C /* net_protocol.c in Sources */,
-                               1583EBAD108395BE00A3BC0C /* net_service.c in Sources */,
-                               1583EBAE108395BE00A3BC0C /* net_set.c in Sources */,
-                               15B274A5114467CD003414AD /* nc.c in Sources */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
                159D53D107528BDA004F8947 /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                                159D541807528E09004F8947 /* dns-configuration.c in Sources */,
                                15D48EBF0F67061600B4711E /* dnsinfo_create.c in Sources */,
                                1522FCFB0FA7FE4B00B24128 /* dnsinfo_flatfile.c in Sources */,
+                               150BEC1814CA24F900237116 /* dnsinfo_server.c in Sources */,
                                159D541707528E05004F8947 /* ip_plugin.c in Sources */,
                                E49173E1137C4E4F0000089F /* network_information_priv.c in Sources */,
+                               153ACCA814E322D5005029A5 /* network_information_server.c in Sources */,
                                1575FD2912CD15C60003D86E /* proxy-configuration.c in Sources */,
                                154361E00752C81800A8EC6C /* set-hostname.c in Sources */,
                                1572EB7B0A506D3B00D02459 /* smb-configuration.c in Sources */,
-                               15D48ED30F67079B00B4711E /* shared_dns_info.defs in Sources */,
+                               1596A7B114EDB73D00798C39 /* libSystemConfiguration_server.c in Sources */,
+                               D61AAEAF1522C99C0066B003 /* scprefs_observer.c in Sources */,
+                               F9A3781016A4847700C57CDC /* IPMonitorControlPrefs.c in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                159D54C407529FFF004F8947 /* _notifycancel.c in Sources */,
                                159D54C507529FFF004F8947 /* _snapshot.c in Sources */,
                                159D54C607529FFF004F8947 /* config.defs in Sources */,
-                               159D54C707529FFF004F8947 /* dnsinfo_private.c in Sources */,
                                159D54C807529FFF004F8947 /* dnsinfo_server.c in Sources */,
-                               159D54C907529FFF004F8947 /* shared_dns_info.defs in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                15A5A2510D5B94190087BDA0 /* dy_framework.c in Sources */,
                                15A5A2530D5B94190087BDA0 /* config.defs in Sources */,
                                15A5A2540D5B94190087BDA0 /* SCPreferencesPathKey.c in Sources */,
-                               15A5A2550D5B94190087BDA0 /* dnsinfo_private.c in Sources */,
-                               15A5A2560D5B94190087BDA0 /* dnsinfo_copy.c in Sources */,
-                               15A5A2570D5B94190087BDA0 /* shared_dns_info.defs in Sources */,
                                15A5A2580D5B94190087BDA0 /* SCNetworkConfigurationInternal.c in Sources */,
                                15A5A2590D5B94190087BDA0 /* SCNetworkInterface.c in Sources */,
                                15A5A25A0D5B94190087BDA0 /* SCNetworkProtocol.c in Sources */,
                                152691DC1129EEAD006BD2D5 /* BridgeConfiguration.c in Sources */,
                                152691DF1129EEC8006BD2D5 /* VLANConfiguration.c in Sources */,
                                15C330BE134B92780028E36B /* SCNetworkReachabilityServer_client.c in Sources */,
-                               15C330C2134B92780028E36B /* rb.c in Sources */,
+                               D61AAEB21522C99C0066B003 /* scprefs_observer.c in Sources */,
+                               C4F1848316237B1400D97043 /* VPNService.c in Sources */,
+                               B0FEF41B1644089200174B99 /* VPNAppLayer.c in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               15AB751416EBFF3400FAA8CE /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               15AB751516EBFF3400FAA8CE /* SCNetworkReachabilityServer_server.c in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               15D3081816F3E4DA00014F82 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               15D3083916F3EB8600014F82 /* simulator_support.c in Sources */,
+                               15C8C6BF170AAB4E005375CE /* cache.c in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
-                               15DAD5E5075913CE0084A6ED /* shared_dns_info.defs in Sources */,
                                15DAD5E6075913CE0084A6ED /* dnsinfo_copy.c in Sources */,
-                               15DAD5E7075913CE0084A6ED /* dnsinfo_private.c in Sources */,
                                D6986A79136891650091C931 /* network_information.c in Sources */,
+                               153338BC14BE7978004FCE22 /* libSystemConfiguration_client.c in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                15DAD68807591A1A0084A6ED /* SCPLock.c in Sources */,
                                15DAD68907591A1A0084A6ED /* SCPUnlock.c in Sources */,
                                15DAD68A07591A1A0084A6ED /* SCPList.c in Sources */,
+                               B0C9689C174426C600889853 /* SNHelper.c in Sources */,
                                15DAD68B07591A1A0084A6ED /* SCPGet.c in Sources */,
                                15DAD68C07591A1A0084A6ED /* SCPAdd.c in Sources */,
                                15DAD68D07591A1A0084A6ED /* SCPSet.c in Sources */,
                                15DAD69F07591A1A0084A6ED /* VLANConfiguration.c in Sources */,
                                15DAD6A007591A1A0084A6ED /* config.defs in Sources */,
                                15DAD6A207591A1A0084A6ED /* SCPreferencesPathKey.c in Sources */,
-                               15DAD6A507591A1A0084A6ED /* shared_dns_info.defs in Sources */,
                                15DAD6A607591A1A0084A6ED /* SCNetworkConfigurationInternal.c in Sources */,
                                15DAD6A707591A1A0084A6ED /* SCNetworkInterface.c in Sources */,
                                15DAD6A807591A1A0084A6ED /* SCNetworkProtocol.c in Sources */,
                                15AAA7F9108E310700C2A607 /* VPNTunnel.c in Sources */,
                                158E595E1107CAE40062081E /* helper.defs in Sources */,
                                15C330BC134B92780028E36B /* SCNetworkReachabilityServer_client.c in Sources */,
-                               15C330C0134B92780028E36B /* rb.c in Sources */,
+                               D61AAEAE1522C99C0066B003 /* scprefs_observer.c in Sources */,
+                               C4F1848016237AFC00D97043 /* VPNService.c in Sources */,
+                               C4CDB8151631935700819B44 /* VPNFlow.c in Sources */,
+                               B03FEFB616376D2800A1B88F /* VPNAppLayer.c in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               15E1B04A16EBAE3C00E5F06F /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               15E1B04B16EBAE3C00E5F06F /* dns-configuration.c in Sources */,
+                               15E1B04C16EBAE3C00E5F06F /* dnsinfo_create.c in Sources */,
+                               15E1B04D16EBAE3C00E5F06F /* dnsinfo_server.c in Sources */,
+                               15E1B04E16EBAE3C00E5F06F /* ip_plugin.c in Sources */,
+                               15E1B04F16EBAE3C00E5F06F /* network_information_priv.c in Sources */,
+                               15E1B05016EBAE3C00E5F06F /* network_information_server.c in Sources */,
+                               15E1B05116EBAE3C00E5F06F /* proxy-configuration.c in Sources */,
+                               15E1B05316EBAE3C00E5F06F /* libSystemConfiguration_server.c in Sources */,
+                               15E1B05416EBAE3C00E5F06F /* scprefs_observer.c in Sources */,
+                               15E1B05516EBAE3C00E5F06F /* IPMonitorControlPrefs.c in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        target = 1528BFF813573FF500691881 /* SCNetworkReachability.bundle-Embedded */;
                        targetProxy = 1528C010135741C300691881 /* PBXContainerItemProxy */;
                };
-               1528C0131357420300691881 /* PBXTargetDependency */ = {
-                       isa = PBXTargetDependency;
-                       target = 1528BFFF1357401900691881 /* SCNetworkReachability-EmbeddedOther */;
-                       targetProxy = 1528C0121357420300691881 /* PBXContainerItemProxy */;
-               };
-               1528C0151357420300691881 /* PBXTargetDependency */ = {
-                       isa = PBXTargetDependency;
-                       target = 1528C0071357401D00691881 /* SCNetworkReachability.bundle-EmbeddedOther */;
-                       targetProxy = 1528C0141357420300691881 /* PBXContainerItemProxy */;
-               };
                1558480607550D470046C2E9 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = 159D549F07529FFF004F8947 /* configd */;
                        target = 156CA4790EF853BB00C59A18 /* Logger.bundle-Embedded */;
                        targetProxy = 156CA4A70EF8550800C59A18 /* PBXContainerItemProxy */;
                };
+               15732AE616EA6BCE00F3AC4C /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = 15732AD616EA6B6700F3AC4C /* libsystem_configuration-EmbeddedSimulator */;
+                       targetProxy = 15732AE516EA6BCE00F3AC4C /* PBXContainerItemProxy */;
+               };
                1574341F0D4A815E002ACA73 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = 157433F00D4A8137002ACA73 /* scutil-Embedded */;
                        target = 157BB8AE075924360025DA7A /* configd_base */;
                        targetProxy = 157BB8C30759244B0025DA7A /* PBXContainerItemProxy */;
                };
+               157FDE44164A079B0040D6A8 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = 157FDE3B164A075F0040D6A8 /* configd_libSystem-EmbeddedSimulator */;
+                       targetProxy = 157FDE43164A079B0040D6A8 /* PBXContainerItemProxy */;
+               };
                15828B070753B77E00AD4710 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = 15828AE60753B5F900AD4710 /* KernelEventMonitor.bundle */;
                        target = 15A5A1E40D5B94190087BDA0 /* SystemConfiguration.framework-EmbeddedSimulator */;
                        targetProxy = 15A5A2700D5B942D0087BDA0 /* PBXContainerItemProxy */;
                };
-               15AC515810839608004A9ED5 /* PBXTargetDependency */ = {
-                       isa = PBXTargetDependency;
-                       target = 1583E9FD108395BB00A3BC0C /* configd_libSystem-EmbeddedOther */;
-                       targetProxy = 15AC515710839608004A9ED5 /* PBXContainerItemProxy */;
-               };
-               15AC515B1083960E004A9ED5 /* PBXTargetDependency */ = {
+               15AB752216EC005A00FAA8CE /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
-                       target = 1583EA11108395BB00A3BC0C /* configd_base-EmbeddedOther */;
-                       targetProxy = 15AC515A1083960E004A9ED5 /* PBXContainerItemProxy */;
+                       target = 15AB751216EBFF3400FAA8CE /* SCNetworkReachability-EmbeddedSimulator */;
+                       targetProxy = 15AB752116EC005A00FAA8CE /* PBXContainerItemProxy */;
                };
-               15AC515D10839613004A9ED5 /* PBXTargetDependency */ = {
+               15AB752416EC005A00FAA8CE /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
-                       target = 1583EAAC108395BB00A3BC0C /* configd_plugins-EmbeddedOther */;
-                       targetProxy = 15AC515C10839613004A9ED5 /* PBXContainerItemProxy */;
+                       target = 15AB751A16EBFF8A00FAA8CE /* SCNetworkReachability.bundle-EmbeddedSimulator */;
+                       targetProxy = 15AB752316EC005A00FAA8CE /* PBXContainerItemProxy */;
                };
-               15AC515F1083961E004A9ED5 /* PBXTargetDependency */ = {
+               15AB752A16EC254D00FAA8CE /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
-                       target = 1583EB41108395BD00A3BC0C /* configd_executables-EmbeddedOther */;
-                       targetProxy = 15AC515E1083961E004A9ED5 /* PBXContainerItemProxy */;
+                       target = 15E1B04116EBAE3C00E5F06F /* IPMonitor-EmbeddedSimulator */;
+                       targetProxy = 15AB752916EC254D00FAA8CE /* PBXContainerItemProxy */;
                };
-               15AC516110839649004A9ED5 /* PBXTargetDependency */ = {
+               15AB752C16EC254D00FAA8CE /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
-                       target = 1583EA04108395BB00A3BC0C /* DNSConfiguration-EmbeddedOther */;
-                       targetProxy = 15AC516010839649004A9ED5 /* PBXContainerItemProxy */;
+                       target = 15AB751216EBFF3400FAA8CE /* SCNetworkReachability-EmbeddedSimulator */;
+                       targetProxy = 15AB752B16EC254D00FAA8CE /* PBXContainerItemProxy */;
                };
-               15AC516310839666004A9ED5 /* PBXTargetDependency */ = {
-                       isa = PBXTargetDependency;
-                       target = 1583EA19108395BB00A3BC0C /* SystemConfiguration.framework-EmbeddedOther */;
-                       targetProxy = 15AC516210839666004A9ED5 /* PBXContainerItemProxy */;
-               };
-               15AC51651083966B004A9ED5 /* PBXTargetDependency */ = {
-                       isa = PBXTargetDependency;
-                       target = 1583EA9B108395BB00A3BC0C /* SCHelper-EmbeddedOther */;
-                       targetProxy = 15AC51641083966B004A9ED5 /* PBXContainerItemProxy */;
-               };
-               15AC516A108396B7004A9ED5 /* PBXTargetDependency */ = {
-                       isa = PBXTargetDependency;
-                       target = 1583EB92108395BE00A3BC0C /* scutil-EmbeddedOther */;
-                       targetProxy = 15AC5169108396B7004A9ED5 /* PBXContainerItemProxy */;
-               };
-               15AC516C108396B7004A9ED5 /* PBXTargetDependency */ = {
-                       isa = PBXTargetDependency;
-                       target = 1583EB86108395BE00A3BC0C /* scselect-EmbeddedOther */;
-                       targetProxy = 15AC516B108396B7004A9ED5 /* PBXContainerItemProxy */;
-               };
-               15AC516E108396B7004A9ED5 /* PBXTargetDependency */ = {
-                       isa = PBXTargetDependency;
-                       target = 1583EB4B108395BD00A3BC0C /* configd-EmbeddedOther */;
-                       targetProxy = 15AC516D108396B7004A9ED5 /* PBXContainerItemProxy */;
-               };
-               15AC5171108396D2004A9ED5 /* PBXTargetDependency */ = {
-                       isa = PBXTargetDependency;
-                       target = 1583EB3A108395BD00A3BC0C /* PreferencesMonitor.bundle-EmbeddedOther */;
-                       targetProxy = 15AC5170108396D2004A9ED5 /* PBXContainerItemProxy */;
-               };
-               15AC5173108396D2004A9ED5 /* PBXTargetDependency */ = {
+               15C64A220F684C4900D78394 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
-                       target = 1583EB32108395BD00A3BC0C /* PreferencesMonitor-EmbeddedOther */;
-                       targetProxy = 15AC5172108396D2004A9ED5 /* PBXContainerItemProxy */;
+                       target = 15DAD5DF075913CE0084A6ED /* libsystem_configuration */;
+                       targetProxy = 15C64A210F684C4900D78394 /* PBXContainerItemProxy */;
                };
-               15AC5179108396D2004A9ED5 /* PBXTargetDependency */ = {
+               15C64A240F684C5700D78394 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
-                       target = 1583EB16108395BC00A3BC0C /* Logger.bundle-EmbeddedOther */;
-                       targetProxy = 15AC5178108396D2004A9ED5 /* PBXContainerItemProxy */;
+                       target = 15C64A1E0F684C3300D78394 /* configd_libSystem */;
+                       targetProxy = 15C64A230F684C5700D78394 /* PBXContainerItemProxy */;
                };
-               15AC517B108396D2004A9ED5 /* PBXTargetDependency */ = {
+               15C64A2F0F684C8300D78394 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
-                       target = 1583EB0F108395BC00A3BC0C /* LinkConfiguration.bundle-EmbeddedOther */;
-                       targetProxy = 15AC517A108396D2004A9ED5 /* PBXContainerItemProxy */;
+                       target = 15C64A280F684C6B00D78394 /* configd_libSystem-Embedded */;
+                       targetProxy = 15C64A2E0F684C8300D78394 /* PBXContainerItemProxy */;
                };
-               15AC517D108396D2004A9ED5 /* PBXTargetDependency */ = {
+               15C64A310F684C8F00D78394 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
-                       target = 1583EB07108395BC00A3BC0C /* LinkConfiguration-EmbeddedOther */;
-                       targetProxy = 15AC517C108396D2004A9ED5 /* PBXContainerItemProxy */;
+                       target = 157A84D80D56C63900B6F1A0 /* libsystem_configuration-Embedded */;
+                       targetProxy = 15C64A300F684C8F00D78394 /* PBXContainerItemProxy */;
                };
-               15AC517F108396D2004A9ED5 /* PBXTargetDependency */ = {
+               15D3083016F3EAD000014F82 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
-                       target = 1583EB00108395BC00A3BC0C /* KernelEventMonitor.bundle-EmbeddedOther */;
-                       targetProxy = 15AC517E108396D2004A9ED5 /* PBXContainerItemProxy */;
+                       target = 15D3080F16F3E4DA00014F82 /* SimulatorSupport-EmbeddedSimulator */;
+                       targetProxy = 15D3082F16F3EAD000014F82 /* PBXContainerItemProxy */;
                };
-               15AC5181108396D2004A9ED5 /* PBXTargetDependency */ = {
+               15D3083216F3EAD000014F82 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
-                       target = 1583EAEF108395BC00A3BC0C /* KernelEventMonitor-EmbeddedOther */;
-                       targetProxy = 15AC5180108396D2004A9ED5 /* PBXContainerItemProxy */;
+                       target = 15D3082816F3E4E100014F82 /* SimulatorSupport.bundle-EmbeddedSimulator */;
+                       targetProxy = 15D3083116F3EAD000014F82 /* PBXContainerItemProxy */;
                };
-               15AC5183108396D2004A9ED5 /* PBXTargetDependency */ = {
+               15D3083516F3EB2500014F82 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
-                       target = 1583EAE8108395BC00A3BC0C /* InterfaceNamer.bundle-EmbeddedOther */;
-                       targetProxy = 15AC5182108396D2004A9ED5 /* PBXContainerItemProxy */;
+                       target = 15D3080F16F3E4DA00014F82 /* SimulatorSupport-EmbeddedSimulator */;
+                       targetProxy = 15D3083416F3EB2500014F82 /* PBXContainerItemProxy */;
                };
-               15AC5185108396D2004A9ED5 /* PBXTargetDependency */ = {
+               15E1B03E16EBAB8A00E5F06F /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
-                       target = 1583EAE0108395BB00A3BC0C /* InterfaceNamer-EmbeddedOther */;
-                       targetProxy = 15AC5184108396D2004A9ED5 /* PBXContainerItemProxy */;
+                       target = 15732A7616EA503200F3AC4C /* configd-EmbeddedSimulator */;
+                       targetProxy = 15E1B03D16EBAB8A00E5F06F /* PBXContainerItemProxy */;
                };
-               15AC5187108396D2004A9ED5 /* PBXTargetDependency */ = {
+               15E1B04016EBAB9400E5F06F /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
-                       target = 1583EAD9108395BB00A3BC0C /* IPMonitor.bundle-EmbeddedOther */;
-                       targetProxy = 15AC5186108396D2004A9ED5 /* PBXContainerItemProxy */;
+                       target = 15732AAD16EA511900F3AC4C /* scutil-EmbeddedSimulator */;
+                       targetProxy = 15E1B03F16EBAB9400E5F06F /* PBXContainerItemProxy */;
                };
-               15AC5189108396D2004A9ED5 /* PBXTargetDependency */ = {
+               15E1B06416EBAF2A00E5F06F /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
-                       target = 1583EACA108395BB00A3BC0C /* IPMonitor-EmbeddedOther */;
-                       targetProxy = 15AC5188108396D2004A9ED5 /* PBXContainerItemProxy */;
+                       target = 15E1B04116EBAE3C00E5F06F /* IPMonitor-EmbeddedSimulator */;
+                       targetProxy = 15E1B06316EBAF2A00E5F06F /* PBXContainerItemProxy */;
                };
-               15C64A220F684C4900D78394 /* PBXTargetDependency */ = {
+               15E1B06616EBAF2A00E5F06F /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
-                       target = 15DAD5DF075913CE0084A6ED /* DNSConfiguration */;
-                       targetProxy = 15C64A210F684C4900D78394 /* PBXContainerItemProxy */;
+                       target = 15E1B05A16EBAE7800E5F06F /* IPMonitor.bundle-EmbeddedSimulator */;
+                       targetProxy = 15E1B06516EBAF2A00E5F06F /* PBXContainerItemProxy */;
                };
-               15C64A240F684C5700D78394 /* PBXTargetDependency */ = {
+               15E83109167F9B0600FD51EC /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
-                       target = 15C64A1E0F684C3300D78394 /* configd_libSystem */;
-                       targetProxy = 15C64A230F684C5700D78394 /* PBXContainerItemProxy */;
+                       target = 15CB690005C0722A0099E85F /* All */;
+                       targetProxy = 15E83108167F9B0600FD51EC /* PBXContainerItemProxy */;
                };
-               15C64A2F0F684C8300D78394 /* PBXTargetDependency */ = {
+               15E8310B167F9B0C00FD51EC /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
-                       target = 15C64A280F684C6B00D78394 /* configd_libSystem-Embedded */;
-                       targetProxy = 15C64A2E0F684C8300D78394 /* PBXContainerItemProxy */;
+                       target = 151C1CC60CFB487000C5AFD6 /* All-Embedded */;
+                       targetProxy = 15E8310A167F9B0C00FD51EC /* PBXContainerItemProxy */;
                };
-               15C64A310F684C8F00D78394 /* PBXTargetDependency */ = {
+               15E8310D167F9B1200FD51EC /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
-                       target = 157A84D80D56C63900B6F1A0 /* DNSConfiguration-Embedded */;
-                       targetProxy = 15C64A300F684C8F00D78394 /* PBXContainerItemProxy */;
+                       target = 15FD13BF0D59485000F9409C /* All-EmbeddedSimulator */;
+                       targetProxy = 15E8310C167F9B1200FD51EC /* PBXContainerItemProxy */;
                };
                D6DDAC3D147A24BC00A2E902 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
 /* Begin XCBuildConfiguration section */
                151C1CC70CFB487000C5AFD6 /* Debug */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                PRODUCT_NAME = "configd (Aggregate/Embedded)";
                        };
                };
                151C1CC80CFB487000C5AFD6 /* Release */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                PRODUCT_NAME = "configd (Aggregate/Embedded)";
                        };
                151F5D9C0CCE98E60093AC3B /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
+                               CODE_SIGN_IDENTITY = "-";
                                DYLIB_COMPATIBILITY_VERSION = 1;
                                DYLIB_CURRENT_VERSION = "$(RC_ProjectSourceVersion)";
                                FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = /System/Library/UserEventPlugins;
                                PRODUCT_NAME = SCMonitor;
+                               PROVISIONING_PROFILE = "";
                                WRAPPER_EXTENSION = plugin;
                        };
                        name = Debug;
                151F5D9D0CCE98E60093AC3B /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
+                               CODE_SIGN_IDENTITY = "-";
                                DYLIB_COMPATIBILITY_VERSION = 1;
                                DYLIB_CURRENT_VERSION = "$(RC_ProjectSourceVersion)";
                                FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = /System/Library/UserEventPlugins;
                                PRODUCT_NAME = SCMonitor;
+                               PROVISIONING_PROFILE = "";
                                WRAPPER_EXTENSION = plugin;
                        };
                        name = Release;
                };
                1528BFF513573FEE00691881 /* Debug */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                DEBUG_INFORMATION_FORMAT = dwarf;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = /usr/local/lib/SystemConfiguration;
                                LIBRARY_STYLE = STATIC;
                                PRODUCT_NAME = SCNetworkReachability;
+                               SDKROOT = iphoneos.internal;
                                STRIP_INSTALLED_PRODUCT = NO;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Debug;
                };
                1528BFF613573FEE00691881 /* Release */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                DEBUG_INFORMATION_FORMAT = dwarf;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = /usr/local/lib/SystemConfiguration;
                                LIBRARY_STYLE = STATIC;
                                PRODUCT_NAME = SCNetworkReachability;
+                               SDKROOT = iphoneos.internal;
                                STRIP_INSTALLED_PRODUCT = NO;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Release;
                };
                1528BFFC13573FF500691881 /* Debug */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                INFOPLIST_FILE = Plugins/SCNetworkReachability/Info.plist;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
                                PRODUCT_NAME = SCNetworkReachability;
+                               SDKROOT = iphoneos.internal;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Debug;
                };
                1528BFFD13573FF500691881 /* Release */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                INFOPLIST_FILE = Plugins/SCNetworkReachability/Info.plist;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
                                PRODUCT_NAME = SCNetworkReachability;
+                               SDKROOT = iphoneos.internal;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Release;
                };
-               1528C0041357401900691881 /* Debug */ = {
+               156CA4830EF853BB00C59A18 /* Debug */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
-                               DEBUG_INFORMATION_FORMAT = dwarf;
+                               INFOPLIST_FILE = "Plugins/Logger/Info-Embedded.plist";
                                INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = /usr/local/lib/SystemConfiguration;
-                               LIBRARY_STYLE = STATIC;
-                               PRODUCT_NAME = SCNetworkReachability;
-                               STRIP_INSTALLED_PRODUCT = NO;
+                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
+                               PRODUCT_NAME = Logger;
+                               SDKROOT = iphoneos.internal;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Debug;
                };
-               1528C0051357401900691881 /* Release */ = {
+               156CA4840EF853BB00C59A18 /* Release */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
-                               DEBUG_INFORMATION_FORMAT = dwarf;
+                               INFOPLIST_FILE = "Plugins/Logger/Info-Embedded.plist";
                                INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = /usr/local/lib/SystemConfiguration;
-                               LIBRARY_STYLE = STATIC;
-                               PRODUCT_NAME = SCNetworkReachability;
-                               STRIP_INSTALLED_PRODUCT = NO;
+                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
+                               PRODUCT_NAME = Logger;
+                               SDKROOT = iphoneos.internal;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Release;
                };
-               1528C00B1357401D00691881 /* Debug */ = {
+               156EB5DB0905594A00EEF749 /* Debug */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
-                               INFOPLIST_FILE = Plugins/SCNetworkReachability/Info.plist;
-                               INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
-                               PRODUCT_NAME = SCNetworkReachability;
-                       };
-                       name = Debug;
-               };
-               1528C00C1357401D00691881 /* Release */ = {
-                       isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
-                       buildSettings = {
-                               INFOPLIST_FILE = Plugins/SCNetworkReachability/Info.plist;
-                               INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
-                               PRODUCT_NAME = SCNetworkReachability;
-                       };
-                       name = Release;
-               };
-               156CA4830EF853BB00C59A18 /* Debug */ = {
-                       isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
-                       buildSettings = {
-                               INFOPLIST_FILE = "Plugins/Logger/Info-Embedded.plist";
-                               INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
-                               PRODUCT_NAME = Logger;
-                       };
-                       name = Debug;
-               };
-               156CA4840EF853BB00C59A18 /* Release */ = {
-                       isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
-                       buildSettings = {
-                               INFOPLIST_FILE = "Plugins/Logger/Info-Embedded.plist";
-                               INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
-                               PRODUCT_NAME = Logger;
-                       };
-                       name = Release;
-               };
-               156EB5DB0905594A00EEF749 /* Debug */ = {
-                       isa = XCBuildConfiguration;
-                       buildSettings = {
-                               BUILD_VARIANTS = (
-                                       normal,
-                                       debug,
-                                       profile,
-                               );
-                               GENERATE_PROFILING_CODE_profile = YES;
-                               INSTALLHDRS_COPY_PHASE = YES;
+                               BUILD_VARIANTS = (
+                                       normal,
+                                       debug,
+                                       profile,
+                               );
+                               GENERATE_PROFILING_CODE_profile = YES;
+                               INSTALLHDRS_COPY_PHASE = YES;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = /usr/lib/system;
-                               LD_DYLIB_INSTALL_NAME = /usr/lib/system/libdnsinfo.dylib;
-                               MACH_O_TYPE = mh_dylib;
+                               LD_DYLIB_INSTALL_NAME = /usr/lib/system/libsystem_configuration.dylib;
+                               LINK_WITH_STANDARD_LIBRARIES = NO;
                                OTHER_CFLAGS_debug = "-O0";
                                OTHER_LDFLAGS = (
-                                       "-umbrella",
-                                       System,
+                                       "-Wl,-umbrella,System",
+                                       "-L/usr/lib/system",
+                                       "-lcompiler_rt",
+                                       "-ldispatch",
+                                       "-ldyld",
+                                       "-lsystem_asl",
+                                       "-lsystem_blocks",
+                                       "-lsystem_c",
+                                       "-lsystem_kernel",
+                                       "-lsystem_malloc",
+                                       "-lsystem_notify",
+                                       "-lsystem_platform",
+                                       "-lsystem_pthread",
+                                       "-lxpc",
                                );
-                               OTHER_MIGFLAGS = "-DLIBDNSINFO";
-                               PRODUCT_NAME = libdnsinfo;
+                               PRODUCT_NAME = libsystem_configuration;
                                STRIP_INSTALLED_PRODUCT_debug = NO;
                                STRIP_INSTALLED_PRODUCT_normal = YES;
                                STRIP_INSTALLED_PRODUCT_profile = NO;
                                INSTALLHDRS_COPY_PHASE = YES;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = /usr/lib/system;
-                               LD_DYLIB_INSTALL_NAME = /usr/lib/system/libdnsinfo.dylib;
-                               MACH_O_TYPE = mh_dylib;
+                               LD_DYLIB_INSTALL_NAME = /usr/lib/system/libsystem_configuration.dylib;
+                               LINK_WITH_STANDARD_LIBRARIES = NO;
                                OTHER_CFLAGS_debug = "-O0";
                                OTHER_CFLAGS_normal = "";
                                OTHER_CFLAGS_profile = "";
                                OTHER_LDFLAGS = (
-                                       "-umbrella",
-                                       System,
+                                       "-Wl,-umbrella,System",
+                                       "-L/usr/lib/system",
+                                       "-lcompiler_rt",
+                                       "-ldispatch",
+                                       "-ldyld",
+                                       "-lsystem_asl",
+                                       "-lsystem_blocks",
+                                       "-lsystem_c",
+                                       "-lsystem_kernel",
+                                       "-lsystem_malloc",
+                                       "-lsystem_notify",
+                                       "-lsystem_platform",
+                                       "-lsystem_pthread",
+                                       "-lxpc",
                                );
-                               OTHER_MIGFLAGS = "-DLIBDNSINFO";
-                               PRODUCT_NAME = libdnsinfo;
+                               PRODUCT_NAME = libsystem_configuration;
                                STRIP_INSTALLED_PRODUCT_debug = NO;
                                STRIP_INSTALLED_PRODUCT_normal = YES;
                                STRIP_INSTALLED_PRODUCT_profile = NO;
                                        "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
                                        "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks",
                                );
-                               HEADER_SEARCH_PATHS = "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders";
+                               HEADER_SEARCH_PATHS = (
+                                       "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders",
+                                       "$(SDKROOT)/usr/local/include/ppp",
+                               );
                                INFOPLIST_FILE = SystemConfiguration.fproj/Info.plist;
                                INSTALLHDRS_SCRIPT_PHASE = YES;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                        "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
                                        "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks",
                                );
-                               HEADER_SEARCH_PATHS = "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders";
+                               HEADER_SEARCH_PATHS = (
+                                       "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders",
+                                       "$(SDKROOT)/usr/local/include/ppp",
+                               );
                                INFOPLIST_FILE = SystemConfiguration.fproj/Info.plist;
                                INSTALLHDRS_SCRIPT_PHASE = YES;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
                                GCC_DYNAMIC_NO_PIC = NO;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/SystemConfiguration.framework/Versions/A/Resources";
+                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/SystemConfiguration.framework/Versions/A/Helpers";
                                PRODUCT_NAME = SCHelper;
                        };
                        name = Debug;
                                FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
                                GCC_DYNAMIC_NO_PIC = NO;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/SystemConfiguration.framework/Versions/A/Resources";
+                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/SystemConfiguration.framework/Versions/A/Helpers";
                                PRODUCT_NAME = SCHelper;
                        };
                        name = Release;
                156EB6230905594A00EEF749 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               CODE_SIGN_IDENTITY = "-";
                                FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
                                GCC_DYNAMIC_NO_PIC = NO;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                156EB6240905594A00EEF749 /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               CODE_SIGN_IDENTITY = "-";
                                FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
                                GCC_DYNAMIC_NO_PIC = NO;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                156EB6270905594A00EEF749 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               CODE_SIGN_IDENTITY = "-";
                                FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
                                GCC_DYNAMIC_NO_PIC = NO;
-                               INSTALL_MODE_FLAG = "a-w,a+rX,u+s";
+                               INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = /usr/sbin;
                                PRODUCT_NAME = scselect;
                        };
                156EB6280905594A00EEF749 /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               CODE_SIGN_IDENTITY = "-";
                                FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
                                GCC_DYNAMIC_NO_PIC = NO;
-                               INSTALL_MODE_FLAG = "a-w,a+rX,u+s";
+                               INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = /usr/sbin;
                                PRODUCT_NAME = scselect;
                        };
                156EB62B0905594A00EEF749 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               CODE_SIGN_IDENTITY = "-";
                                FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
                                GCC_DYNAMIC_NO_PIC = NO;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                156EB62C0905594A00EEF749 /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               CODE_SIGN_IDENTITY = "-";
                                FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
                                GCC_DYNAMIC_NO_PIC = NO;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                DYLIB_CURRENT_VERSION = "$(RC_ProjectSourceVersion)";
                                GCC_OPTIMIZATION_LEVEL = 0;
                                INSTALL_GROUP = wheel;
-                               INSTALL_MODE_FLAG = "u+s,ugo-w,o+rX";
                                INSTALL_OWNER = root;
                                INSTALL_PATH = /usr/sbin;
                                OTHER_CFLAGS = (
                                        "-fconstant-cfstrings",
-                                       "-fstack-protector",
+                                       "-fstack-protector-all",
                                        "-D_FORTIFY_SOURCE=2",
                                );
                                RUN_CLANG_STATIC_ANALYZER = YES;
                                DYLIB_COMPATIBILITY_VERSION = 1;
                                DYLIB_CURRENT_VERSION = "$(RC_ProjectSourceVersion)";
                                INSTALL_GROUP = wheel;
-                               INSTALL_MODE_FLAG = "u+s,ugo-w,o+rX";
                                INSTALL_OWNER = root;
                                INSTALL_PATH = /usr/sbin;
                                OTHER_CFLAGS = (
                                        "-fconstant-cfstrings",
-                                       "-fstack-protector",
+                                       "-fstack-protector-all",
                                        "-D_FORTIFY_SOURCE=2",
                                );
                                VERSIONING_SYSTEM = "apple-generic";
                };
                1572C52A0CFB55B400E2776E /* Debug */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
-                               HEADER_SEARCH_PATHS = "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders";
+                               HEADER_SEARCH_PATHS = (
+                                       "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders",
+                                       "$(SDKROOT)/usr/local/include/ppp",
+                               );
                                INFOPLIST_FILE = "SystemConfiguration.fproj/Info-Embedded.plist";
                                INSTALLHDRS_SCRIPT_PHASE = YES;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks";
                                LIBRARY_SEARCH_PATHS = "$(SYMROOT)";
                                PRODUCT_NAME = SystemConfiguration;
+                               SDKROOT = iphoneos.internal;
+                               SUPPORTED_PLATFORMS = iphoneos;
                                WRAPPER_EXTENSION = framework;
                        };
                        name = Debug;
                };
                1572C52B0CFB55B400E2776E /* Release */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
-                               HEADER_SEARCH_PATHS = "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders";
+                               HEADER_SEARCH_PATHS = (
+                                       "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders",
+                                       "$(SDKROOT)/usr/local/include/ppp",
+                               );
                                INFOPLIST_FILE = "SystemConfiguration.fproj/Info-Embedded.plist";
                                INSTALLHDRS_SCRIPT_PHASE = YES;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks";
                                LIBRARY_SEARCH_PATHS = "$(SYMROOT)";
                                PRODUCT_NAME = SystemConfiguration;
+                               SDKROOT = iphoneos.internal;
+                               SUPPORTED_PLATFORMS = iphoneos;
                                WRAPPER_EXTENSION = framework;
                        };
                        name = Release;
                };
+               15732AAA16EA503200F3AC4C /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       baseConfigurationReference = 15FD147B0D594FE700F9409C /* IndigoSDK.xcconfig */;
+                       buildSettings = {
+                               APPLY_RULES_IN_COPY_FILES = YES;
+                               CODE_SIGN_IDENTITY = "-";
+                               FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
+                               INSTALL_MODE_FLAG = "a-w,a+rX";
+                               INSTALL_PATH_ACTUAL = /usr/libexec;
+                               LIBRARY_SEARCH_PATHS = (
+                                       "$(SYMROOT)",
+                                       "$(SDKROOT)/usr/local/lib/SystemConfiguration",
+                               );
+                               PRODUCT_NAME = configd_sim;
+                       };
+                       name = Debug;
+               };
+               15732AAB16EA503200F3AC4C /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       baseConfigurationReference = 15FD147B0D594FE700F9409C /* IndigoSDK.xcconfig */;
+                       buildSettings = {
+                               APPLY_RULES_IN_COPY_FILES = YES;
+                               CODE_SIGN_IDENTITY = "-";
+                               FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
+                               INSTALL_MODE_FLAG = "a-w,a+rX";
+                               INSTALL_PATH_ACTUAL = /usr/libexec;
+                               LIBRARY_SEARCH_PATHS = (
+                                       "$(SYMROOT)",
+                                       "$(SDKROOT)/usr/local/lib/SystemConfiguration",
+                               );
+                               PRODUCT_NAME = configd_sim;
+                       };
+                       name = Release;
+               };
+               15732AD316EA511900F3AC4C /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       baseConfigurationReference = 15FD147B0D594FE700F9409C /* IndigoSDK.xcconfig */;
+                       buildSettings = {
+                               FRAMEWORK_SEARCH_PATHS = (
+                                       "$(SYMROOT)",
+                                       "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
+                               );
+                               INSTALL_MODE_FLAG = "a-w,a+rX";
+                               INSTALL_PATH_ACTUAL = /usr/local/bin;
+                               LIBRARY_SEARCH_PATHS = (
+                                       "$(SYMROOT)",
+                                       "$(SDKROOT)/usr/local/lib/SystemConfiguration",
+                               );
+                               PRODUCT_NAME = scutil_sim;
+                       };
+                       name = Debug;
+               };
+               15732AD416EA511900F3AC4C /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       baseConfigurationReference = 15FD147B0D594FE700F9409C /* IndigoSDK.xcconfig */;
+                       buildSettings = {
+                               FRAMEWORK_SEARCH_PATHS = (
+                                       "$(SYMROOT)",
+                                       "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
+                               );
+                               INSTALL_MODE_FLAG = "a-w,a+rX";
+                               INSTALL_PATH_ACTUAL = /usr/local/bin;
+                               LIBRARY_SEARCH_PATHS = (
+                                       "$(SYMROOT)",
+                                       "$(SDKROOT)/usr/local/lib/SystemConfiguration",
+                               );
+                               PRODUCT_NAME = scutil_sim;
+                       };
+                       name = Release;
+               };
+               15732AE216EA6B6700F3AC4C /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       baseConfigurationReference = 15FD147B0D594FE700F9409C /* IndigoSDK.xcconfig */;
+                       buildSettings = {
+                               BUILD_VARIANTS = (
+                                       normal,
+                                       debug,
+                                       profile,
+                               );
+                               FRAMEWORK_SEARCH_PATHS = "$(inherited)";
+                               GENERATE_PROFILING_CODE_profile = YES;
+                               INSTALLHDRS_COPY_PHASE = YES;
+                               INSTALL_MODE_FLAG = "a-w,a+rX";
+                               INSTALL_PATH_ACTUAL = /usr/lib/system;
+                               LD_DYLIB_INSTALL_NAME = /usr/lib/system/libsystem_sim_configuration.dylib;
+                               LIBRARY_SEARCH_PATHS = "$(SDKDIR)/usr/lib";
+                               LINK_WITH_STANDARD_LIBRARIES = NO;
+                               OTHER_CFLAGS_debug = "-O0";
+                               OTHER_CFLAGS_normal = "";
+                               OTHER_CFLAGS_profile = "";
+                               OTHER_LDFLAGS = (
+                                       "-Wl,-umbrella,System",
+                                       "-L$(INDIGO_INSTALL_PATH_PREFIX)/usr/lib/system",
+                                       "-lcompiler_rt_sim",
+                                       "-ldispatch",
+                                       "-ldyld_sim",
+                                       "-lsystem_sim_blocks",
+                                       "-lsystem_sim_c",
+                                       "-lxpc",
+                                       "-Wl,-upward-lSystem",
+                               );
+                               PRIVATE_HEADERS_FOLDER_PATH = "$(SDKROOT)/usr/local/include";
+                               PRODUCT_NAME = libsystem_sim_configuration;
+                               PUBLIC_HEADERS_FOLDER_PATH = "$(SDKROOT)/usr/local/include";
+                               STRIP_INSTALLED_PRODUCT_debug = NO;
+                               STRIP_INSTALLED_PRODUCT_normal = YES;
+                               STRIP_INSTALLED_PRODUCT_profile = NO;
+                       };
+                       name = Debug;
+               };
+               15732AE316EA6B6700F3AC4C /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       baseConfigurationReference = 15FD147B0D594FE700F9409C /* IndigoSDK.xcconfig */;
+                       buildSettings = {
+                               BUILD_VARIANTS = (
+                                       normal,
+                                       debug,
+                                       profile,
+                               );
+                               FRAMEWORK_SEARCH_PATHS = "$(inherited)";
+                               GENERATE_PROFILING_CODE_profile = YES;
+                               INSTALLHDRS_COPY_PHASE = YES;
+                               INSTALL_MODE_FLAG = "a-w,a+rX";
+                               INSTALL_PATH_ACTUAL = /usr/lib/system;
+                               LD_DYLIB_INSTALL_NAME = /usr/lib/system/libsystem_sim_configuration.dylib;
+                               LIBRARY_SEARCH_PATHS = "$(SDKDIR)/usr/lib";
+                               LINK_WITH_STANDARD_LIBRARIES = NO;
+                               OTHER_CFLAGS_debug = "-O0";
+                               OTHER_CFLAGS_normal = "";
+                               OTHER_CFLAGS_profile = "";
+                               OTHER_LDFLAGS = (
+                                       "-Wl,-umbrella,System",
+                                       "-L$(INDIGO_INSTALL_PATH_PREFIX)/usr/lib/system",
+                                       "-lcompiler_rt_sim",
+                                       "-ldispatch",
+                                       "-ldyld_sim",
+                                       "-lsystem_sim_blocks",
+                                       "-lsystem_sim_c",
+                                       "-lxpc",
+                                       "-Wl,-upward-lSystem",
+                               );
+                               PRIVATE_HEADERS_FOLDER_PATH = "$(SDKROOT)/usr/local/include";
+                               PRODUCT_NAME = libsystem_sim_configuration;
+                               PUBLIC_HEADERS_FOLDER_PATH = "$(SDKROOT)/usr/local/include";
+                               STRIP_INSTALLED_PRODUCT_debug = NO;
+                               STRIP_INSTALLED_PRODUCT_normal = YES;
+                               STRIP_INSTALLED_PRODUCT_profile = NO;
+                       };
+                       name = Release;
+               };
                157433E90D4A8122002ACA73 /* Debug */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
-                               INSTALL_MODE_FLAG = "a-w,a+rX,u+s";
                                INSTALL_PATH = /usr/sbin;
                                PRODUCT_NAME = scselect;
+                               SDKROOT = iphoneos.internal;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Debug;
                };
                157433EA0D4A8122002ACA73 /* Release */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
-                               INSTALL_MODE_FLAG = "a-w,a+rX,u+s";
                                INSTALL_PATH = /usr/sbin;
                                PRODUCT_NAME = scselect;
+                               SDKROOT = iphoneos.internal;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Release;
                };
                157434170D4A8137002ACA73 /* Debug */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
-                               FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
+                               FRAMEWORK_SEARCH_PATHS = (
+                                       "$(SYMROOT)",
+                                       "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
+                               );
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = /usr/sbin;
                                LIBRARY_SEARCH_PATHS = (
                                        "$(SDKROOT)/usr/local/lib/SystemConfiguration",
                                );
                                PRODUCT_NAME = scutil;
+                               SDKROOT = iphoneos.internal;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Debug;
                };
                157434180D4A8137002ACA73 /* Release */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
-                               FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
+                               FRAMEWORK_SEARCH_PATHS = (
+                                       "$(SYMROOT)",
+                                       "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
+                               );
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = /usr/sbin;
                                LIBRARY_SEARCH_PATHS = (
                                        "$(SDKROOT)/usr/local/lib/SystemConfiguration",
                                );
                                PRODUCT_NAME = scutil;
+                               SDKROOT = iphoneos.internal;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Release;
                };
                157A84E50D56C63900B6F1A0 /* Debug */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                BUILD_VARIANTS = (
                                        normal,
                                INSTALLHDRS_COPY_PHASE = YES;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = /usr/lib/system;
-                               LD_DYLIB_INSTALL_NAME = /usr/lib/system/libdnsinfo.dylib;
-                               MACH_O_TYPE = mh_dylib;
+                               LD_DYLIB_INSTALL_NAME = /usr/lib/system/libsystem_configuration.dylib;
+                               LINK_WITH_STANDARD_LIBRARIES = NO;
                                OTHER_CFLAGS_debug = "-O0";
                                OTHER_CFLAGS_normal = "";
                                OTHER_CFLAGS_profile = "";
                                OTHER_LDFLAGS = (
-                                       "-umbrella",
-                                       System,
+                                       "-Wl,-umbrella,System",
+                                       "-L/usr/lib/system",
+                                       "-lcompiler_rt",
+                                       "-ldispatch",
+                                       "-ldyld",
+                                       "-lsystem_asl",
+                                       "-lsystem_blocks",
+                                       "-lsystem_c",
+                                       "-lsystem_kernel",
+                                       "-lsystem_malloc",
+                                       "-lsystem_notify",
+                                       "-lsystem_platform",
+                                       "-lsystem_pthread",
+                                       "-lxpc",
+                                       "-Wl,-upward-lSystem",
                                );
-                               OTHER_MIGFLAGS = "-DLIBDNSINFO";
-                               PRODUCT_NAME = libdnsinfo;
+                               PRODUCT_NAME = libsystem_configuration;
+                               SDKROOT = iphoneos.internal;
                                STRIP_INSTALLED_PRODUCT_debug = NO;
                                STRIP_INSTALLED_PRODUCT_normal = YES;
                                STRIP_INSTALLED_PRODUCT_profile = NO;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Debug;
                };
                157A84E60D56C63900B6F1A0 /* Release */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                BUILD_VARIANTS = (
                                        normal,
                                INSTALLHDRS_COPY_PHASE = YES;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = /usr/lib/system;
-                               LD_DYLIB_INSTALL_NAME = /usr/lib/system/libdnsinfo.dylib;
-                               MACH_O_TYPE = mh_dylib;
+                               LD_DYLIB_INSTALL_NAME = /usr/lib/system/libsystem_configuration.dylib;
+                               LINK_WITH_STANDARD_LIBRARIES = NO;
                                OTHER_CFLAGS_debug = "-O0";
                                OTHER_CFLAGS_normal = "";
                                OTHER_CFLAGS_profile = "";
                                OTHER_LDFLAGS = (
-                                       "-umbrella",
-                                       System,
+                                       "-Wl,-umbrella,System",
+                                       "-L/usr/lib/system",
+                                       "-lcompiler_rt",
+                                       "-ldispatch",
+                                       "-ldyld",
+                                       "-lsystem_asl",
+                                       "-lsystem_blocks",
+                                       "-lsystem_c",
+                                       "-lsystem_kernel",
+                                       "-lsystem_malloc",
+                                       "-lsystem_notify",
+                                       "-lsystem_platform",
+                                       "-lsystem_pthread",
+                                       "-lxpc",
+                                       "-Wl,-upward-lSystem",
                                );
-                               OTHER_MIGFLAGS = "-DLIBDNSINFO";
-                               PRODUCT_NAME = libdnsinfo;
+                               PRODUCT_NAME = libsystem_configuration;
+                               SDKROOT = iphoneos.internal;
                                STRIP_INSTALLED_PRODUCT_debug = NO;
                                STRIP_INSTALLED_PRODUCT_normal = YES;
                                STRIP_INSTALLED_PRODUCT_profile = NO;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Release;
                };
                157A84FF0D56C7E800B6F1A0 /* Debug */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                DEBUG_INFORMATION_FORMAT = dwarf;
                                HEADER_SEARCH_PATHS = "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders";
                                INSTALL_PATH = /usr/local/lib/SystemConfiguration;
                                LIBRARY_STYLE = STATIC;
                                PRODUCT_NAME = IPMonitor;
+                               SDKROOT = iphoneos.internal;
                                STRIP_INSTALLED_PRODUCT = NO;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Debug;
                };
                157A85000D56C7E800B6F1A0 /* Release */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                DEBUG_INFORMATION_FORMAT = dwarf;
                                HEADER_SEARCH_PATHS = "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders";
                                INSTALL_PATH = /usr/local/lib/SystemConfiguration;
                                LIBRARY_STYLE = STATIC;
                                PRODUCT_NAME = IPMonitor;
+                               SDKROOT = iphoneos.internal;
                                STRIP_INSTALLED_PRODUCT = NO;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Release;
                };
                157A850A0D56C8AA00B6F1A0 /* Debug */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                DEBUG_INFORMATION_FORMAT = dwarf;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = /usr/local/lib/SystemConfiguration;
                                LIBRARY_STYLE = STATIC;
                                PRODUCT_NAME = InterfaceNamer;
+                               SDKROOT = iphoneos.internal;
                                STRIP_INSTALLED_PRODUCT = NO;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Debug;
                };
                157A850B0D56C8AA00B6F1A0 /* Release */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                DEBUG_INFORMATION_FORMAT = dwarf;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = /usr/local/lib/SystemConfiguration;
                                LIBRARY_STYLE = STATIC;
                                PRODUCT_NAME = InterfaceNamer;
+                               SDKROOT = iphoneos.internal;
                                STRIP_INSTALLED_PRODUCT = NO;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Release;
                };
                157A85200D56C8E000B6F1A0 /* Debug */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                DEBUG_INFORMATION_FORMAT = dwarf;
                                HEADER_SEARCH_PATHS = "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders";
                                INSTALL_PATH = /usr/local/lib/SystemConfiguration;
                                LIBRARY_STYLE = STATIC;
                                PRODUCT_NAME = KernelEventMonitor;
+                               SDKROOT = iphoneos.internal;
                                STRIP_INSTALLED_PRODUCT = NO;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Debug;
                };
                157A85210D56C8E000B6F1A0 /* Release */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                DEBUG_INFORMATION_FORMAT = dwarf;
                                HEADER_SEARCH_PATHS = "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders";
                                INSTALL_PATH = /usr/local/lib/SystemConfiguration;
                                LIBRARY_STYLE = STATIC;
                                PRODUCT_NAME = KernelEventMonitor;
+                               SDKROOT = iphoneos.internal;
                                STRIP_INSTALLED_PRODUCT = NO;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Release;
                };
                157A852B0D56C91100B6F1A0 /* Debug */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                DEBUG_INFORMATION_FORMAT = dwarf;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = /usr/local/lib/SystemConfiguration;
                                LIBRARY_STYLE = STATIC;
                                PRODUCT_NAME = LinkConfiguration;
+                               SDKROOT = iphoneos.internal;
                                STRIP_INSTALLED_PRODUCT = NO;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Debug;
                };
                157A852C0D56C91100B6F1A0 /* Release */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                DEBUG_INFORMATION_FORMAT = dwarf;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = /usr/local/lib/SystemConfiguration;
                                LIBRARY_STYLE = STATIC;
                                PRODUCT_NAME = LinkConfiguration;
+                               SDKROOT = iphoneos.internal;
                                STRIP_INSTALLED_PRODUCT = NO;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Release;
                };
                157A85410D56C96F00B6F1A0 /* Debug */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                DEBUG_INFORMATION_FORMAT = dwarf;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = /usr/local/lib/SystemConfiguration;
                                LIBRARY_STYLE = STATIC;
                                PRODUCT_NAME = PreferencesMonitor;
+                               SDKROOT = iphoneos.internal;
                                STRIP_INSTALLED_PRODUCT = NO;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Debug;
                };
                157A85420D56C96F00B6F1A0 /* Release */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                DEBUG_INFORMATION_FORMAT = dwarf;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = /usr/local/lib/SystemConfiguration;
                                LIBRARY_STYLE = STATIC;
                                PRODUCT_NAME = PreferencesMonitor;
+                               SDKROOT = iphoneos.internal;
                                STRIP_INSTALLED_PRODUCT = NO;
+                               SUPPORTED_PLATFORMS = iphoneos;
+                       };
+                       name = Release;
+               };
+               157FDE3F164A075F0040D6A8 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       baseConfigurationReference = 15FD147B0D594FE700F9409C /* IndigoSDK.xcconfig */;
+                       buildSettings = {
+                               INSTALLHDRS_COPY_PHASE = YES;
+                               PRODUCT_NAME = "configd_libSystem (EmbeddedSimulator)";
+                       };
+                       name = Debug;
+               };
+               157FDE40164A075F0040D6A8 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       baseConfigurationReference = 15FD147B0D594FE700F9409C /* IndigoSDK.xcconfig */;
+                       buildSettings = {
+                               INSTALLHDRS_COPY_PHASE = YES;
+                               PRODUCT_NAME = "configd_libSystem (EmbeddedSimulator)";
                        };
                        name = Release;
                };
                158316D90CFB774B006F62B9 /* Debug */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                PRODUCT_NAME = "configd_base (Embedded)";
                        };
                };
                158316DA0CFB774B006F62B9 /* Release */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                PRODUCT_NAME = "configd_base (Embedded)";
                        };
                };
                158317010CFB7761006F62B9 /* Debug */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                PRODUCT_NAME = "configd_plugins (Embedded)";
                        };
                };
                158317020CFB7761006F62B9 /* Release */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                PRODUCT_NAME = "configd_plugins (Embedded)";
                        };
                };
                1583170C0CFB7782006F62B9 /* Debug */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                PRODUCT_NAME = "configd_executables (Embedded)";
                        };
                };
                1583170D0CFB7782006F62B9 /* Release */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                PRODUCT_NAME = "configd_executables (Embedded)";
                        };
                };
                1583175E0CFB80A1006F62B9 /* Debug */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                APPLY_RULES_IN_COPY_FILES = YES;
                                CODE_SIGN_ENTITLEMENTS = configd.tproj/entitlements.plist;
+                               CODE_SIGN_IDENTITY = "-";
                                FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = /usr/libexec;
                                        "$(SDKROOT)/usr/local/lib/SystemConfiguration",
                                );
                                PRODUCT_NAME = configd;
+                               SDKROOT = iphoneos.internal;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Debug;
                };
                1583175F0CFB80A1006F62B9 /* Release */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                APPLY_RULES_IN_COPY_FILES = YES;
                                CODE_SIGN_ENTITLEMENTS = configd.tproj/entitlements.plist;
+                               CODE_SIGN_IDENTITY = "-";
                                FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = /usr/libexec;
                                        "$(SDKROOT)/usr/local/lib/SystemConfiguration",
                                );
                                PRODUCT_NAME = configd;
+                               SDKROOT = iphoneos.internal;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Release;
                };
                158317810CFB85C8006F62B9 /* Debug */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                INFOPLIST_FILE = Plugins/IPMonitor/Info.plist;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
                                PRODUCT_NAME = IPMonitor;
+                               SDKROOT = iphoneos.internal;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Debug;
                };
                158317820CFB85C8006F62B9 /* Release */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                INFOPLIST_FILE = Plugins/IPMonitor/Info.plist;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
                                PRODUCT_NAME = IPMonitor;
+                               SDKROOT = iphoneos.internal;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Release;
                };
                1583178A0CFB85DD006F62B9 /* Debug */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                INFOPLIST_FILE = Plugins/InterfaceNamer/Info.plist;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
                                PRODUCT_NAME = InterfaceNamer;
+                               SDKROOT = iphoneos.internal;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Debug;
                };
                1583178B0CFB85DD006F62B9 /* Release */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                INFOPLIST_FILE = Plugins/InterfaceNamer/Info.plist;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
                                PRODUCT_NAME = InterfaceNamer;
+                               SDKROOT = iphoneos.internal;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Release;
                };
                158317930CFB85F7006F62B9 /* Debug */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                INFOPLIST_FILE = Plugins/KernelEventMonitor/Info.plist;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
                                PRODUCT_NAME = KernelEventMonitor;
+                               SDKROOT = iphoneos.internal;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Debug;
                };
                158317940CFB85F7006F62B9 /* Release */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                INFOPLIST_FILE = Plugins/KernelEventMonitor/Info.plist;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
                                PRODUCT_NAME = KernelEventMonitor;
+                               SDKROOT = iphoneos.internal;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Release;
                };
                1583179B0CFB860C006F62B9 /* Debug */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                INFOPLIST_FILE = Plugins/LinkConfiguration/Info.plist;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
                                PRODUCT_NAME = LinkConfiguration;
+                               SDKROOT = iphoneos.internal;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Debug;
                };
                1583179C0CFB860C006F62B9 /* Release */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                INFOPLIST_FILE = Plugins/LinkConfiguration/Info.plist;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
                                PRODUCT_NAME = LinkConfiguration;
+                               SDKROOT = iphoneos.internal;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Release;
                };
                158317AB0CFB8639006F62B9 /* Debug */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                INFOPLIST_FILE = Plugins/PreferencesMonitor/Info.plist;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
                                PRODUCT_NAME = PreferencesMonitor;
+                               SDKROOT = iphoneos.internal;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Debug;
                };
                158317AC0CFB8639006F62B9 /* Release */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                INFOPLIST_FILE = Plugins/PreferencesMonitor/Info.plist;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
                                PRODUCT_NAME = PreferencesMonitor;
+                               SDKROOT = iphoneos.internal;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Release;
                };
                158337A70CFB6B9E0033AB93 /* Debug */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                APPLY_RULES_IN_COPY_FILES = YES;
                                FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/SystemConfiguration.framework";
                                PRODUCT_NAME = SCHelper;
+                               SDKROOT = iphoneos.internal;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Debug;
                };
                158337A80CFB6B9E0033AB93 /* Release */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
                                APPLY_RULES_IN_COPY_FILES = YES;
                                FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
                                INSTALL_MODE_FLAG = "a-w,a+rX";
                                INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/SystemConfiguration.framework";
                                PRODUCT_NAME = SCHelper;
+                               SDKROOT = iphoneos.internal;
+                               SUPPORTED_PLATFORMS = iphoneos;
                        };
                        name = Release;
                };
-               1583E9EA1083959E00A3BC0C /* Debug */ = {
+               15A5A2670D5B94190087BDA0 /* Debug */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
+                       baseConfigurationReference = 15FD147B0D594FE700F9409C /* IndigoSDK.xcconfig */;
                        buildSettings = {
-                               PRODUCT_NAME = "configd (Aggregate/EmbeddedOther)";
+                               HEADER_SEARCH_PATHS = (
+                                       "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders",
+                                       "$(SDKROOT)/usr/local/include/ppp",
+                               );
+                               INFOPLIST_FILE = "SystemConfiguration.fproj/Info-Embedded.plist";
+                               INSTALLHDRS_SCRIPT_PHASE = YES;
+                               INSTALL_MODE_FLAG = "a-w,a+rX";
+                               INSTALL_PATH_ACTUAL = "$(SYSTEM_LIBRARY_DIR)/Frameworks";
+                               LIBRARY_SEARCH_PATHS = "$(SYMROOT)";
+                               OTHER_CFLAGS = (
+                                       "-idirafter",
+                                       "$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders",
+                               );
+                               PRODUCT_NAME = SystemConfiguration;
+                               WRAPPER_EXTENSION = framework;
                        };
                        name = Debug;
                };
-               1583E9EB1083959E00A3BC0C /* Release */ = {
+               15A5A2680D5B94190087BDA0 /* Release */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
+                       baseConfigurationReference = 15FD147B0D594FE700F9409C /* IndigoSDK.xcconfig */;
                        buildSettings = {
-                               PRODUCT_NAME = "configd (Aggregate/EmbeddedOther)";
+                               HEADER_SEARCH_PATHS = (
+                                       "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders",
+                                       "$(SDKROOT)/usr/local/include/ppp",
+                               );
+                               INFOPLIST_FILE = "SystemConfiguration.fproj/Info-Embedded.plist";
+                               INSTALLHDRS_SCRIPT_PHASE = YES;
+                               INSTALL_MODE_FLAG = "a-w,a+rX";
+                               INSTALL_PATH_ACTUAL = "$(SYSTEM_LIBRARY_DIR)/Frameworks";
+                               LIBRARY_SEARCH_PATHS = "$(SYMROOT)";
+                               OTHER_CFLAGS = (
+                                       "-idirafter",
+                                       "$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders",
+                               );
+                               PRODUCT_NAME = SystemConfiguration;
+                               WRAPPER_EXTENSION = framework;
                        };
                        name = Release;
                };
-               1583EA02108395BB00A3BC0C /* Debug */ = {
+               15AB751716EBFF3400FAA8CE /* Debug */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
+                       baseConfigurationReference = 15FD147B0D594FE700F9409C /* IndigoSDK.xcconfig */;
                        buildSettings = {
-                               INSTALL_PATH = /usr/local/lib/system;
-                               PRODUCT_NAME = "configd_libSystem (EmbeddedOther)";
+                               DEBUG_INFORMATION_FORMAT = dwarf;
+                               INSTALL_MODE_FLAG = "a-w,a+rX";
+                               INSTALL_PATH_ACTUAL = /usr/local/lib/SystemConfiguration;
+                               LIBRARY_STYLE = STATIC;
+                               PRODUCT_NAME = SCNetworkReachability_sim;
+                               STRIP_INSTALLED_PRODUCT = NO;
                        };
                        name = Debug;
                };
-               1583EA03108395BB00A3BC0C /* Release */ = {
+               15AB751816EBFF3400FAA8CE /* Release */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
+                       baseConfigurationReference = 15FD147B0D594FE700F9409C /* IndigoSDK.xcconfig */;
                        buildSettings = {
-                               INSTALL_PATH = /usr/local/lib/system;
-                               PRODUCT_NAME = "configd_libSystem (EmbeddedOther)";
+                               DEBUG_INFORMATION_FORMAT = dwarf;
+                               INSTALL_MODE_FLAG = "a-w,a+rX";
+                               INSTALL_PATH_ACTUAL = /usr/local/lib/SystemConfiguration;
+                               LIBRARY_STYLE = STATIC;
+                               PRODUCT_NAME = SCNetworkReachability_sim;
+                               STRIP_INSTALLED_PRODUCT = NO;
                        };
                        name = Release;
                };
-               1583EA0E108395BB00A3BC0C /* Debug */ = {
+               15AB751D16EBFF8A00FAA8CE /* Debug */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
+                       baseConfigurationReference = 15FD147B0D594FE700F9409C /* IndigoSDK.xcconfig */;
                        buildSettings = {
-                               BUILD_VARIANTS = (
-                                       normal,
-                                       debug,
-                                       profile,
-                               );
-                               GENERATE_PROFILING_CODE_profile = YES;
-                               INSTALLHDRS_COPY_PHASE = YES;
+                               INFOPLIST_FILE = Plugins/SCNetworkReachability/Info.plist;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = /usr/lib/system;
-                               LD_DYLIB_INSTALL_NAME = /usr/lib/system/libdnsinfo.dylib;
-                               MACH_O_TYPE = mh_dylib;
-                               OTHER_CFLAGS_debug = "-O0";
-                               OTHER_CFLAGS_normal = "";
-                               OTHER_CFLAGS_profile = "";
-                               OTHER_LDFLAGS = (
-                                       "-umbrella",
-                                       System,
-                               );
-                               OTHER_MIGFLAGS = "-DLIBDNSINFO";
-                               PRODUCT_NAME = libdnsinfo;
-                               STRIP_INSTALLED_PRODUCT_debug = NO;
-                               STRIP_INSTALLED_PRODUCT_normal = YES;
-                               STRIP_INSTALLED_PRODUCT_profile = NO;
+                               INSTALL_PATH_ACTUAL = /System/Library/SystemConfiguration;
+                               PRODUCT_NAME = SCNetworkReachability;
                        };
                        name = Debug;
                };
-               1583EA0F108395BB00A3BC0C /* Release */ = {
+               15AB751E16EBFF8A00FAA8CE /* Release */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
+                       baseConfigurationReference = 15FD147B0D594FE700F9409C /* IndigoSDK.xcconfig */;
                        buildSettings = {
-                               BUILD_VARIANTS = (
-                                       normal,
-                                       debug,
-                                       profile,
-                               );
-                               GENERATE_PROFILING_CODE_profile = YES;
-                               INSTALLHDRS_COPY_PHASE = YES;
+                               INFOPLIST_FILE = Plugins/SCNetworkReachability/Info.plist;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = /usr/lib/system;
-                               LD_DYLIB_INSTALL_NAME = /usr/lib/system/libdnsinfo.dylib;
-                               MACH_O_TYPE = mh_dylib;
-                               OTHER_CFLAGS_debug = "-O0";
-                               OTHER_CFLAGS_normal = "";
-                               OTHER_CFLAGS_profile = "";
-                               OTHER_LDFLAGS = (
-                                       "-umbrella",
-                                       System,
-                               );
-                               OTHER_MIGFLAGS = "-DLIBDNSINFO";
-                               PRODUCT_NAME = libdnsinfo;
-                               STRIP_INSTALLED_PRODUCT_debug = NO;
-                               STRIP_INSTALLED_PRODUCT_normal = YES;
-                               STRIP_INSTALLED_PRODUCT_profile = NO;
-                       };
-                       name = Release;
-               };
-               1583EA17108395BB00A3BC0C /* Debug */ = {
-                       isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
-                       buildSettings = {
-                               PRODUCT_NAME = "configd_base (EmbeddedOther)";
-                       };
-                       name = Debug;
-               };
-               1583EA18108395BB00A3BC0C /* Release */ = {
-                       isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
-                       buildSettings = {
-                               PRODUCT_NAME = "configd_base (EmbeddedOther)";
-                       };
-                       name = Release;
-               };
-               1583EA97108395BB00A3BC0C /* Debug */ = {
-                       isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
-                       buildSettings = {
-                               GCC_PREPROCESSOR_DEFINITIONS = TARGET_OS_EMBEDDED_OTHER;
-                               HEADER_SEARCH_PATHS = "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders";
-                               INFOPLIST_FILE = SystemConfiguration.fproj/Info.plist;
-                               INSTALLHDRS_SCRIPT_PHASE = YES;
-                               INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks";
-                               LIBRARY_SEARCH_PATHS = "$(SYMROOT)";
-                               PRODUCT_NAME = SystemConfiguration;
-                               WRAPPER_EXTENSION = framework;
-                       };
-                       name = Debug;
-               };
-               1583EA98108395BB00A3BC0C /* Release */ = {
-                       isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
-                       buildSettings = {
-                               GCC_PREPROCESSOR_DEFINITIONS = TARGET_OS_EMBEDDED_OTHER;
-                               HEADER_SEARCH_PATHS = "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders";
-                               INFOPLIST_FILE = SystemConfiguration.fproj/Info.plist;
-                               INSTALLHDRS_SCRIPT_PHASE = YES;
-                               INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks";
-                               LIBRARY_SEARCH_PATHS = "$(SYMROOT)";
-                               PRODUCT_NAME = SystemConfiguration;
-                               WRAPPER_EXTENSION = framework;
-                       };
-                       name = Release;
-               };
-               1583EAA8108395BB00A3BC0C /* Debug */ = {
-                       isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
-                       buildSettings = {
-                               APPLY_RULES_IN_COPY_FILES = YES;
-                               FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
-                               INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/SystemConfiguration.framework";
-                               PRODUCT_NAME = SCHelper;
-                       };
-                       name = Debug;
-               };
-               1583EAA9108395BB00A3BC0C /* Release */ = {
-                       isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
-                       buildSettings = {
-                               APPLY_RULES_IN_COPY_FILES = YES;
-                               FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
-                               INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/SystemConfiguration.framework";
-                               PRODUCT_NAME = SCHelper;
-                       };
-                       name = Release;
-               };
-               1583EAC8108395BB00A3BC0C /* Debug */ = {
-                       isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
-                       buildSettings = {
-                               PRODUCT_NAME = "configd_plugins (EmbeddedOther)";
-                       };
-                       name = Debug;
-               };
-               1583EAC9108395BB00A3BC0C /* Release */ = {
-                       isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
-                       buildSettings = {
-                               PRODUCT_NAME = "configd_plugins (EmbeddedOther)";
-                       };
-                       name = Release;
-               };
-               1583EAD6108395BB00A3BC0C /* Debug */ = {
-                       isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
-                       buildSettings = {
-                               DEBUG_INFORMATION_FORMAT = dwarf;
-                               INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = /usr/local/lib/SystemConfiguration;
-                               LIBRARY_STYLE = STATIC;
-                               PRODUCT_NAME = IPMonitor;
-                               STRIP_INSTALLED_PRODUCT = NO;
-                       };
-                       name = Debug;
-               };
-               1583EAD7108395BB00A3BC0C /* Release */ = {
-                       isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
-                       buildSettings = {
-                               DEBUG_INFORMATION_FORMAT = dwarf;
-                               INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = /usr/local/lib/SystemConfiguration;
-                               LIBRARY_STYLE = STATIC;
-                               PRODUCT_NAME = IPMonitor;
-                               STRIP_INSTALLED_PRODUCT = NO;
-                       };
-                       name = Release;
-               };
-               1583EADC108395BB00A3BC0C /* Debug */ = {
-                       isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
-                       buildSettings = {
-                               INFOPLIST_FILE = Plugins/IPMonitor/Info.plist;
-                               INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
-                               PRODUCT_NAME = IPMonitor;
-                       };
-                       name = Debug;
-               };
-               1583EADD108395BB00A3BC0C /* Release */ = {
-                       isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
-                       buildSettings = {
-                               INFOPLIST_FILE = Plugins/IPMonitor/Info.plist;
-                               INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
-                               PRODUCT_NAME = IPMonitor;
-                       };
-                       name = Release;
-               };
-               1583EAE5108395BB00A3BC0C /* Debug */ = {
-                       isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
-                       buildSettings = {
-                               DEBUG_INFORMATION_FORMAT = dwarf;
-                               INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = /usr/local/lib/SystemConfiguration;
-                               LIBRARY_STYLE = STATIC;
-                               PRODUCT_NAME = InterfaceNamer;
-                               STRIP_INSTALLED_PRODUCT = NO;
-                       };
-                       name = Debug;
-               };
-               1583EAE6108395BB00A3BC0C /* Release */ = {
-                       isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
-                       buildSettings = {
-                               DEBUG_INFORMATION_FORMAT = dwarf;
-                               INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = /usr/local/lib/SystemConfiguration;
-                               LIBRARY_STYLE = STATIC;
-                               PRODUCT_NAME = InterfaceNamer;
-                               STRIP_INSTALLED_PRODUCT = NO;
-                       };
-                       name = Release;
-               };
-               1583EAEB108395BC00A3BC0C /* Debug */ = {
-                       isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
-                       buildSettings = {
-                               INFOPLIST_FILE = Plugins/InterfaceNamer/Info.plist;
-                               INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
-                               PRODUCT_NAME = InterfaceNamer;
-                       };
-                       name = Debug;
-               };
-               1583EAEC108395BC00A3BC0C /* Release */ = {
-                       isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
-                       buildSettings = {
-                               INFOPLIST_FILE = Plugins/InterfaceNamer/Info.plist;
-                               INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
-                               PRODUCT_NAME = InterfaceNamer;
-                       };
-                       name = Release;
-               };
-               1583EAFD108395BC00A3BC0C /* Debug */ = {
-                       isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
-                       buildSettings = {
-                               DEBUG_INFORMATION_FORMAT = dwarf;
-                               HEADER_SEARCH_PATHS = "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders";
-                               INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = /usr/local/lib/SystemConfiguration;
-                               LIBRARY_STYLE = STATIC;
-                               PRODUCT_NAME = KernelEventMonitor;
-                               STRIP_INSTALLED_PRODUCT = NO;
-                       };
-                       name = Debug;
-               };
-               1583EAFE108395BC00A3BC0C /* Release */ = {
-                       isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
-                       buildSettings = {
-                               DEBUG_INFORMATION_FORMAT = dwarf;
-                               HEADER_SEARCH_PATHS = "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders";
-                               INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = /usr/local/lib/SystemConfiguration;
-                               LIBRARY_STYLE = STATIC;
-                               PRODUCT_NAME = KernelEventMonitor;
-                               STRIP_INSTALLED_PRODUCT = NO;
-                       };
-                       name = Release;
-               };
-               1583EB03108395BC00A3BC0C /* Debug */ = {
-                       isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
-                       buildSettings = {
-                               INFOPLIST_FILE = Plugins/KernelEventMonitor/Info.plist;
-                               INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
-                               PRODUCT_NAME = KernelEventMonitor;
-                       };
-                       name = Debug;
-               };
-               1583EB04108395BC00A3BC0C /* Release */ = {
-                       isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
-                       buildSettings = {
-                               INFOPLIST_FILE = Plugins/KernelEventMonitor/Info.plist;
-                               INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
-                               PRODUCT_NAME = KernelEventMonitor;
-                       };
-                       name = Release;
-               };
-               1583EB0C108395BC00A3BC0C /* Debug */ = {
-                       isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
-                       buildSettings = {
-                               DEBUG_INFORMATION_FORMAT = dwarf;
-                               INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = /usr/local/lib/SystemConfiguration;
-                               LIBRARY_STYLE = STATIC;
-                               PRODUCT_NAME = LinkConfiguration;
-                               STRIP_INSTALLED_PRODUCT = NO;
-                       };
-                       name = Debug;
-               };
-               1583EB0D108395BC00A3BC0C /* Release */ = {
-                       isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
-                       buildSettings = {
-                               DEBUG_INFORMATION_FORMAT = dwarf;
-                               INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = /usr/local/lib/SystemConfiguration;
-                               LIBRARY_STYLE = STATIC;
-                               PRODUCT_NAME = LinkConfiguration;
-                               STRIP_INSTALLED_PRODUCT = NO;
-                       };
-                       name = Release;
-               };
-               1583EB12108395BC00A3BC0C /* Debug */ = {
-                       isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
-                       buildSettings = {
-                               INFOPLIST_FILE = Plugins/LinkConfiguration/Info.plist;
-                               INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
-                               PRODUCT_NAME = LinkConfiguration;
-                       };
-                       name = Debug;
-               };
-               1583EB13108395BC00A3BC0C /* Release */ = {
-                       isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
-                       buildSettings = {
-                               INFOPLIST_FILE = Plugins/LinkConfiguration/Info.plist;
-                               INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
-                               PRODUCT_NAME = LinkConfiguration;
-                       };
-                       name = Release;
-               };
-               1583EB1F108395BC00A3BC0C /* Debug */ = {
-                       isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
-                       buildSettings = {
-                               INFOPLIST_FILE = "Plugins/Logger/Info-Embedded.plist";
-                               INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
-                               PRODUCT_NAME = Logger;
-                       };
-                       name = Debug;
-               };
-               1583EB20108395BC00A3BC0C /* Release */ = {
-                       isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
-                       buildSettings = {
-                               INFOPLIST_FILE = "Plugins/Logger/Info-Embedded.plist";
-                               INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
-                               PRODUCT_NAME = Logger;
-                       };
-                       name = Release;
-               };
-               1583EB37108395BD00A3BC0C /* Debug */ = {
-                       isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
-                       buildSettings = {
-                               DEBUG_INFORMATION_FORMAT = dwarf;
-                               INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = /usr/local/lib/SystemConfiguration;
-                               LIBRARY_STYLE = STATIC;
-                               PRODUCT_NAME = PreferencesMonitor;
-                               STRIP_INSTALLED_PRODUCT = NO;
-                       };
-                       name = Debug;
-               };
-               1583EB38108395BD00A3BC0C /* Release */ = {
-                       isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
-                       buildSettings = {
-                               DEBUG_INFORMATION_FORMAT = dwarf;
-                               INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = /usr/local/lib/SystemConfiguration;
-                               LIBRARY_STYLE = STATIC;
-                               PRODUCT_NAME = PreferencesMonitor;
-                               STRIP_INSTALLED_PRODUCT = NO;
-                       };
-                       name = Release;
-               };
-               1583EB3D108395BD00A3BC0C /* Debug */ = {
-                       isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
-                       buildSettings = {
-                               INFOPLIST_FILE = Plugins/PreferencesMonitor/Info.plist;
-                               INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
-                               PRODUCT_NAME = PreferencesMonitor;
-                       };
-                       name = Debug;
-               };
-               1583EB3E108395BD00A3BC0C /* Release */ = {
-                       isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
-                       buildSettings = {
-                               INFOPLIST_FILE = Plugins/PreferencesMonitor/Info.plist;
-                               INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
-                               PRODUCT_NAME = PreferencesMonitor;
+                               INSTALL_PATH_ACTUAL = /System/Library/SystemConfiguration;
+                               PRODUCT_NAME = SCNetworkReachability;
                        };
                        name = Release;
                };
-               1583EB49108395BD00A3BC0C /* Debug */ = {
+               15C64A1F0F684C3300D78394 /* Debug */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
-                               PRODUCT_NAME = "configd_executables (EmbeddedOther)";
+                               INSTALL_PATH = /usr/local/lib/system;
+                               PRODUCT_NAME = configd_libSystem;
                        };
                        name = Debug;
                };
-               1583EB4A108395BD00A3BC0C /* Release */ = {
+               15C64A200F684C3300D78394 /* Release */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
-                               PRODUCT_NAME = "configd_executables (EmbeddedOther)";
+                               INSTALL_PATH = /usr/local/lib/system;
+                               PRODUCT_NAME = configd_libSystem;
                        };
                        name = Release;
                };
-               1583EB82108395BD00A3BC0C /* Debug */ = {
+               15C64A2C0F684C6B00D78394 /* Debug */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
-                               APPLY_RULES_IN_COPY_FILES = YES;
-                               CODE_SIGN_ENTITLEMENTS = configd.tproj/entitlements.plist;
-                               FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
-                               GCC_PREPROCESSOR_DEFINITIONS = TARGET_OS_EMBEDDED_OTHER;
-                               INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = /usr/libexec;
-                               LIBRARY_SEARCH_PATHS = (
-                                       "$(SYMROOT)",
-                                       "$(SDKROOT)/usr/local/lib/SystemConfiguration",
-                               );
-                               PRODUCT_NAME = configd;
+                               INSTALL_PATH = /usr/local/lib/system;
+                               PRODUCT_NAME = "configd_libSystem (Embedded)";
                        };
                        name = Debug;
                };
-               1583EB83108395BD00A3BC0C /* Release */ = {
+               15C64A2D0F684C6B00D78394 /* Release */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
-                               APPLY_RULES_IN_COPY_FILES = YES;
-                               CODE_SIGN_ENTITLEMENTS = configd.tproj/entitlements.plist;
-                               FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
-                               GCC_PREPROCESSOR_DEFINITIONS = TARGET_OS_EMBEDDED_OTHER;
-                               INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = /usr/libexec;
-                               LIBRARY_SEARCH_PATHS = (
-                                       "$(SYMROOT)",
-                                       "$(SDKROOT)/usr/local/lib/SystemConfiguration",
-                               );
-                               PRODUCT_NAME = configd;
+                               INSTALL_PATH = /usr/local/lib/system;
+                               PRODUCT_NAME = "configd_libSystem (Embedded)";
                        };
                        name = Release;
                };
-               1583EB8E108395BE00A3BC0C /* Debug */ = {
+               15D3082516F3E4DA00014F82 /* Debug */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
+                       baseConfigurationReference = 15FD147B0D594FE700F9409C /* IndigoSDK.xcconfig */;
                        buildSettings = {
-                               FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
-                               INSTALL_MODE_FLAG = "a-w,a+rX,u+s";
-                               INSTALL_PATH = /usr/sbin;
-                               PRODUCT_NAME = scselect;
+                               DEBUG_INFORMATION_FORMAT = dwarf;
+                               HEADER_SEARCH_PATHS = "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders";
+                               INSTALL_MODE_FLAG = "a-w,a+rX";
+                               INSTALL_PATH_ACTUAL = /usr/local/lib/SystemConfiguration;
+                               LIBRARY_STYLE = STATIC;
+                               PRODUCT_NAME = SimulatorSupport_sim;
+                               STRIP_INSTALLED_PRODUCT = NO;
                        };
                        name = Debug;
                };
-               1583EB8F108395BE00A3BC0C /* Release */ = {
+               15D3082616F3E4DA00014F82 /* Release */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
+                       baseConfigurationReference = 15FD147B0D594FE700F9409C /* IndigoSDK.xcconfig */;
                        buildSettings = {
-                               FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
-                               INSTALL_MODE_FLAG = "a-w,a+rX,u+s";
-                               INSTALL_PATH = /usr/sbin;
-                               PRODUCT_NAME = scselect;
+                               DEBUG_INFORMATION_FORMAT = dwarf;
+                               HEADER_SEARCH_PATHS = "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders";
+                               INSTALL_MODE_FLAG = "a-w,a+rX";
+                               INSTALL_PATH_ACTUAL = /usr/local/lib/SystemConfiguration;
+                               LIBRARY_STYLE = STATIC;
+                               PRODUCT_NAME = SimulatorSupport_sim;
+                               STRIP_INSTALLED_PRODUCT = NO;
                        };
                        name = Release;
                };
-               1583EBB4108395BE00A3BC0C /* Debug */ = {
+               15D3082B16F3E4E100014F82 /* Debug */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
+                       baseConfigurationReference = 15FD147B0D594FE700F9409C /* IndigoSDK.xcconfig */;
                        buildSettings = {
-                               FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
+                               INFOPLIST_FILE = Plugins/SimulatorSupport/Info.plist;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = /usr/sbin;
-                               LIBRARY_SEARCH_PATHS = (
-                                       "$(SYMROOT)",
-                                       "$(SDKROOT)/usr/local/lib/SystemConfiguration",
-                               );
-                               PRODUCT_NAME = scutil;
+                               INSTALL_PATH_ACTUAL = /System/Library/SystemConfiguration;
+                               PRODUCT_NAME = SimulatorSupport;
                        };
                        name = Debug;
                };
-               1583EBB5108395BE00A3BC0C /* Release */ = {
+               15D3082C16F3E4E100014F82 /* Release */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
+                       baseConfigurationReference = 15FD147B0D594FE700F9409C /* IndigoSDK.xcconfig */;
                        buildSettings = {
-                               FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
+                               INFOPLIST_FILE = Plugins/SimulatorSupport/Info.plist;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH = /usr/sbin;
-                               LIBRARY_SEARCH_PATHS = (
-                                       "$(SYMROOT)",
-                                       "$(SDKROOT)/usr/local/lib/SystemConfiguration",
-                               );
-                               PRODUCT_NAME = scutil;
+                               INSTALL_PATH_ACTUAL = /System/Library/SystemConfiguration;
+                               PRODUCT_NAME = SimulatorSupport;
                        };
                        name = Release;
                };
-               15A5A2670D5B94190087BDA0 /* Debug */ = {
+               15E1B05716EBAE3C00E5F06F /* Debug */ = {
                        isa = XCBuildConfiguration;
                        baseConfigurationReference = 15FD147B0D594FE700F9409C /* IndigoSDK.xcconfig */;
                        buildSettings = {
+                               DEBUG_INFORMATION_FORMAT = dwarf;
                                HEADER_SEARCH_PATHS = "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders";
-                               INFOPLIST_FILE = "SystemConfiguration.fproj/Info-Embedded.plist";
-                               INSTALLHDRS_SCRIPT_PHASE = YES;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH_ACTUAL = "$(SYSTEM_LIBRARY_DIR)/Frameworks";
-                               LIBRARY_SEARCH_PATHS = "$(SYMROOT)";
-                               OTHER_CFLAGS = (
-                                       "-idirafter",
-                                       "$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders",
-                               );
-                               PRODUCT_NAME = SystemConfiguration;
-                               WRAPPER_EXTENSION = framework;
+                               INSTALL_PATH_ACTUAL = /usr/local/lib/SystemConfiguration;
+                               LIBRARY_STYLE = STATIC;
+                               PRODUCT_NAME = IPMonitor_sim;
+                               STRIP_INSTALLED_PRODUCT = NO;
                        };
                        name = Debug;
                };
-               15A5A2680D5B94190087BDA0 /* Release */ = {
+               15E1B05816EBAE3C00E5F06F /* Release */ = {
                        isa = XCBuildConfiguration;
                        baseConfigurationReference = 15FD147B0D594FE700F9409C /* IndigoSDK.xcconfig */;
                        buildSettings = {
+                               DEBUG_INFORMATION_FORMAT = dwarf;
                                HEADER_SEARCH_PATHS = "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders";
-                               INFOPLIST_FILE = "SystemConfiguration.fproj/Info-Embedded.plist";
-                               INSTALLHDRS_SCRIPT_PHASE = YES;
                                INSTALL_MODE_FLAG = "a-w,a+rX";
-                               INSTALL_PATH_ACTUAL = "$(SYSTEM_LIBRARY_DIR)/Frameworks";
-                               LIBRARY_SEARCH_PATHS = "$(SYMROOT)";
-                               OTHER_CFLAGS = (
-                                       "-idirafter",
-                                       "$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders",
-                               );
-                               PRODUCT_NAME = SystemConfiguration;
-                               WRAPPER_EXTENSION = framework;
+                               INSTALL_PATH_ACTUAL = /usr/local/lib/SystemConfiguration;
+                               LIBRARY_STYLE = STATIC;
+                               PRODUCT_NAME = IPMonitor_sim;
+                               STRIP_INSTALLED_PRODUCT = NO;
                        };
                        name = Release;
                };
-               15C64A1F0F684C3300D78394 /* Debug */ = {
+               15E1B05F16EBAE7800E5F06F /* Debug */ = {
                        isa = XCBuildConfiguration;
+                       baseConfigurationReference = 15FD147B0D594FE700F9409C /* IndigoSDK.xcconfig */;
                        buildSettings = {
-                               INSTALL_PATH = /usr/local/lib/system;
-                               PRODUCT_NAME = configd_libSystem;
+                               INFOPLIST_FILE = Plugins/IPMonitor/Info.plist;
+                               INSTALL_MODE_FLAG = "a-w,a+rX";
+                               INSTALL_PATH_ACTUAL = /System/Library/SystemConfiguration;
+                               PRODUCT_NAME = IPMonitor;
                        };
                        name = Debug;
                };
-               15C64A200F684C3300D78394 /* Release */ = {
+               15E1B06016EBAE7800E5F06F /* Release */ = {
                        isa = XCBuildConfiguration;
+                       baseConfigurationReference = 15FD147B0D594FE700F9409C /* IndigoSDK.xcconfig */;
                        buildSettings = {
-                               INSTALL_PATH = /usr/local/lib/system;
-                               PRODUCT_NAME = configd_libSystem;
+                               INFOPLIST_FILE = Plugins/IPMonitor/Info.plist;
+                               INSTALL_MODE_FLAG = "a-w,a+rX";
+                               INSTALL_PATH_ACTUAL = /System/Library/SystemConfiguration;
+                               PRODUCT_NAME = IPMonitor;
                        };
                        name = Release;
                };
-               15C64A2C0F684C6B00D78394 /* Debug */ = {
+               15E83105167F9AF600FD51EC /* Debug */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
-                               INSTALL_PATH = /usr/local/lib/system;
-                               PRODUCT_NAME = "configd_libSystem (Embedded)";
+                               PRODUCT_NAME = "$(TARGET_NAME)";
                        };
                        name = Debug;
                };
-               15C64A2D0F684C6B00D78394 /* Release */ = {
+               15E83106167F9AF600FD51EC /* Release */ = {
                        isa = XCBuildConfiguration;
-                       baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
                        buildSettings = {
-                               INSTALL_PATH = /usr/local/lib/system;
-                               PRODUCT_NAME = "configd_libSystem (Embedded)";
+                               PRODUCT_NAME = "$(TARGET_NAME)";
                        };
                        name = Release;
                };
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
-               1528C0031357401900691881 /* Build configuration list for PBXNativeTarget "SCNetworkReachability-EmbeddedOther" */ = {
-                       isa = XCConfigurationList;
-                       buildConfigurations = (
-                               1528C0041357401900691881 /* Debug */,
-                               1528C0051357401900691881 /* Release */,
-                       );
-                       defaultConfigurationIsVisible = 0;
-                       defaultConfigurationName = Release;
-               };
-               1528C00A1357401D00691881 /* Build configuration list for PBXNativeTarget "SCNetworkReachability.bundle-EmbeddedOther" */ = {
-                       isa = XCConfigurationList;
-                       buildConfigurations = (
-                               1528C00B1357401D00691881 /* Debug */,
-                               1528C00C1357401D00691881 /* Release */,
-                       );
-                       defaultConfigurationIsVisible = 0;
-                       defaultConfigurationName = Release;
-               };
                156CA4820EF853BB00C59A18 /* Build configuration list for PBXNativeTarget "Logger.bundle-Embedded" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
-               156EB5DA0905594A00EEF749 /* Build configuration list for PBXNativeTarget "DNSConfiguration" */ = {
+               156EB5DA0905594A00EEF749 /* Build configuration list for PBXNativeTarget "libsystem_configuration" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
                                156EB5DB0905594A00EEF749 /* Debug */,
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
+               15732AA916EA503200F3AC4C /* Build configuration list for PBXNativeTarget "configd-EmbeddedSimulator" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               15732AAA16EA503200F3AC4C /* Debug */,
+                               15732AAB16EA503200F3AC4C /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               15732AD216EA511900F3AC4C /* Build configuration list for PBXNativeTarget "scutil-EmbeddedSimulator" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               15732AD316EA511900F3AC4C /* Debug */,
+                               15732AD416EA511900F3AC4C /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               15732AE116EA6B6700F3AC4C /* Build configuration list for PBXNativeTarget "libsystem_configuration-EmbeddedSimulator" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               15732AE216EA6B6700F3AC4C /* Debug */,
+                               15732AE316EA6B6700F3AC4C /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
                157433E80D4A8122002ACA73 /* Build configuration list for PBXNativeTarget "scselect-Embedded" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
-               157A84E40D56C63900B6F1A0 /* Build configuration list for PBXNativeTarget "DNSConfiguration-Embedded" */ = {
+               157A84E40D56C63900B6F1A0 /* Build configuration list for PBXNativeTarget "libsystem_configuration-Embedded" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
                                157A84E50D56C63900B6F1A0 /* Debug */,
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
+               157FDE3E164A075F0040D6A8 /* Build configuration list for PBXAggregateTarget "configd_libSystem-EmbeddedSimulator" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               157FDE3F164A075F0040D6A8 /* Debug */,
+                               157FDE40164A075F0040D6A8 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
                158316D80CFB774B006F62B9 /* Build configuration list for PBXAggregateTarget "configd_base-Embedded" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
-               1583E9E91083959E00A3BC0C /* Build configuration list for PBXAggregateTarget "All-EmbeddedOther" */ = {
-                       isa = XCConfigurationList;
-                       buildConfigurations = (
-                               1583E9EA1083959E00A3BC0C /* Debug */,
-                               1583E9EB1083959E00A3BC0C /* Release */,
-                       );
-                       defaultConfigurationIsVisible = 0;
-                       defaultConfigurationName = Release;
-               };
-               1583EA01108395BB00A3BC0C /* Build configuration list for PBXAggregateTarget "configd_libSystem-EmbeddedOther" */ = {
-                       isa = XCConfigurationList;
-                       buildConfigurations = (
-                               1583EA02108395BB00A3BC0C /* Debug */,
-                               1583EA03108395BB00A3BC0C /* Release */,
-                       );
-                       defaultConfigurationIsVisible = 0;
-                       defaultConfigurationName = Release;
-               };
-               1583EA0D108395BB00A3BC0C /* Build configuration list for PBXNativeTarget "DNSConfiguration-EmbeddedOther" */ = {
-                       isa = XCConfigurationList;
-                       buildConfigurations = (
-                               1583EA0E108395BB00A3BC0C /* Debug */,
-                               1583EA0F108395BB00A3BC0C /* Release */,
-                       );
-                       defaultConfigurationIsVisible = 0;
-                       defaultConfigurationName = Release;
-               };
-               1583EA16108395BB00A3BC0C /* Build configuration list for PBXAggregateTarget "configd_base-EmbeddedOther" */ = {
-                       isa = XCConfigurationList;
-                       buildConfigurations = (
-                               1583EA17108395BB00A3BC0C /* Debug */,
-                               1583EA18108395BB00A3BC0C /* Release */,
-                       );
-                       defaultConfigurationIsVisible = 0;
-                       defaultConfigurationName = Release;
-               };
-               1583EA96108395BB00A3BC0C /* Build configuration list for PBXNativeTarget "SystemConfiguration.framework-EmbeddedOther" */ = {
-                       isa = XCConfigurationList;
-                       buildConfigurations = (
-                               1583EA97108395BB00A3BC0C /* Debug */,
-                               1583EA98108395BB00A3BC0C /* Release */,
-                       );
-                       defaultConfigurationIsVisible = 0;
-                       defaultConfigurationName = Release;
-               };
-               1583EAA7108395BB00A3BC0C /* Build configuration list for PBXNativeTarget "SCHelper-EmbeddedOther" */ = {
-                       isa = XCConfigurationList;
-                       buildConfigurations = (
-                               1583EAA8108395BB00A3BC0C /* Debug */,
-                               1583EAA9108395BB00A3BC0C /* Release */,
-                       );
-                       defaultConfigurationIsVisible = 0;
-                       defaultConfigurationName = Release;
-               };
-               1583EAC7108395BB00A3BC0C /* Build configuration list for PBXAggregateTarget "configd_plugins-EmbeddedOther" */ = {
-                       isa = XCConfigurationList;
-                       buildConfigurations = (
-                               1583EAC8108395BB00A3BC0C /* Debug */,
-                               1583EAC9108395BB00A3BC0C /* Release */,
-                       );
-                       defaultConfigurationIsVisible = 0;
-                       defaultConfigurationName = Release;
-               };
-               1583EAD5108395BB00A3BC0C /* Build configuration list for PBXNativeTarget "IPMonitor-EmbeddedOther" */ = {
-                       isa = XCConfigurationList;
-                       buildConfigurations = (
-                               1583EAD6108395BB00A3BC0C /* Debug */,
-                               1583EAD7108395BB00A3BC0C /* Release */,
-                       );
-                       defaultConfigurationIsVisible = 0;
-                       defaultConfigurationName = Release;
-               };
-               1583EADB108395BB00A3BC0C /* Build configuration list for PBXNativeTarget "IPMonitor.bundle-EmbeddedOther" */ = {
-                       isa = XCConfigurationList;
-                       buildConfigurations = (
-                               1583EADC108395BB00A3BC0C /* Debug */,
-                               1583EADD108395BB00A3BC0C /* Release */,
-                       );
-                       defaultConfigurationIsVisible = 0;
-                       defaultConfigurationName = Release;
-               };
-               1583EAE4108395BB00A3BC0C /* Build configuration list for PBXNativeTarget "InterfaceNamer-EmbeddedOther" */ = {
-                       isa = XCConfigurationList;
-                       buildConfigurations = (
-                               1583EAE5108395BB00A3BC0C /* Debug */,
-                               1583EAE6108395BB00A3BC0C /* Release */,
-                       );
-                       defaultConfigurationIsVisible = 0;
-                       defaultConfigurationName = Release;
-               };
-               1583EAEA108395BC00A3BC0C /* Build configuration list for PBXNativeTarget "InterfaceNamer.bundle-EmbeddedOther" */ = {
-                       isa = XCConfigurationList;
-                       buildConfigurations = (
-                               1583EAEB108395BC00A3BC0C /* Debug */,
-                               1583EAEC108395BC00A3BC0C /* Release */,
-                       );
-                       defaultConfigurationIsVisible = 0;
-                       defaultConfigurationName = Release;
-               };
-               1583EAFC108395BC00A3BC0C /* Build configuration list for PBXNativeTarget "KernelEventMonitor-EmbeddedOther" */ = {
-                       isa = XCConfigurationList;
-                       buildConfigurations = (
-                               1583EAFD108395BC00A3BC0C /* Debug */,
-                               1583EAFE108395BC00A3BC0C /* Release */,
-                       );
-                       defaultConfigurationIsVisible = 0;
-                       defaultConfigurationName = Release;
-               };
-               1583EB02108395BC00A3BC0C /* Build configuration list for PBXNativeTarget "KernelEventMonitor.bundle-EmbeddedOther" */ = {
-                       isa = XCConfigurationList;
-                       buildConfigurations = (
-                               1583EB03108395BC00A3BC0C /* Debug */,
-                               1583EB04108395BC00A3BC0C /* Release */,
-                       );
-                       defaultConfigurationIsVisible = 0;
-                       defaultConfigurationName = Release;
-               };
-               1583EB0B108395BC00A3BC0C /* Build configuration list for PBXNativeTarget "LinkConfiguration-EmbeddedOther" */ = {
-                       isa = XCConfigurationList;
-                       buildConfigurations = (
-                               1583EB0C108395BC00A3BC0C /* Debug */,
-                               1583EB0D108395BC00A3BC0C /* Release */,
-                       );
-                       defaultConfigurationIsVisible = 0;
-                       defaultConfigurationName = Release;
-               };
-               1583EB11108395BC00A3BC0C /* Build configuration list for PBXNativeTarget "LinkConfiguration.bundle-EmbeddedOther" */ = {
-                       isa = XCConfigurationList;
-                       buildConfigurations = (
-                               1583EB12108395BC00A3BC0C /* Debug */,
-                               1583EB13108395BC00A3BC0C /* Release */,
-                       );
-                       defaultConfigurationIsVisible = 0;
-                       defaultConfigurationName = Release;
-               };
-               1583EB1E108395BC00A3BC0C /* Build configuration list for PBXNativeTarget "Logger.bundle-EmbeddedOther" */ = {
+               15A5A2660D5B94190087BDA0 /* Build configuration list for PBXNativeTarget "SystemConfiguration.framework-EmbeddedSimulator" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
-                               1583EB1F108395BC00A3BC0C /* Debug */,
-                               1583EB20108395BC00A3BC0C /* Release */,
+                               15A5A2670D5B94190087BDA0 /* Debug */,
+                               15A5A2680D5B94190087BDA0 /* Release */,
                        );
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
-               1583EB36108395BD00A3BC0C /* Build configuration list for PBXNativeTarget "PreferencesMonitor-EmbeddedOther" */ = {
+               15AB751616EBFF3400FAA8CE /* Build configuration list for PBXNativeTarget "SCNetworkReachability-EmbeddedSimulator" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
-                               1583EB37108395BD00A3BC0C /* Debug */,
-                               1583EB38108395BD00A3BC0C /* Release */,
+                               15AB751716EBFF3400FAA8CE /* Debug */,
+                               15AB751816EBFF3400FAA8CE /* Release */,
                        );
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
-               1583EB3C108395BD00A3BC0C /* Build configuration list for PBXNativeTarget "PreferencesMonitor.bundle-EmbeddedOther" */ = {
+               15AB751C16EBFF8A00FAA8CE /* Build configuration list for PBXNativeTarget "SCNetworkReachability.bundle-EmbeddedSimulator" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
-                               1583EB3D108395BD00A3BC0C /* Debug */,
-                               1583EB3E108395BD00A3BC0C /* Release */,
+                               15AB751D16EBFF8A00FAA8CE /* Debug */,
+                               15AB751E16EBFF8A00FAA8CE /* Release */,
                        );
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
-               1583EB48108395BD00A3BC0C /* Build configuration list for PBXAggregateTarget "configd_executables-EmbeddedOther" */ = {
+               15C64A270F684C6B00D78394 /* Build configuration list for PBXAggregateTarget "configd_libSystem" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
-                               1583EB49108395BD00A3BC0C /* Debug */,
-                               1583EB4A108395BD00A3BC0C /* Release */,
+                               15C64A1F0F684C3300D78394 /* Debug */,
+                               15C64A200F684C3300D78394 /* Release */,
                        );
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
-               1583EB81108395BD00A3BC0C /* Build configuration list for PBXNativeTarget "configd-EmbeddedOther" */ = {
+               15C64A2B0F684C6B00D78394 /* Build configuration list for PBXAggregateTarget "configd_libSystem-Embedded" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
-                               1583EB82108395BD00A3BC0C /* Debug */,
-                               1583EB83108395BD00A3BC0C /* Release */,
+                               15C64A2C0F684C6B00D78394 /* Debug */,
+                               15C64A2D0F684C6B00D78394 /* Release */,
                        );
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
-               1583EB8D108395BE00A3BC0C /* Build configuration list for PBXNativeTarget "scselect-EmbeddedOther" */ = {
+               15D3082416F3E4DA00014F82 /* Build configuration list for PBXNativeTarget "SimulatorSupport-EmbeddedSimulator" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
-                               1583EB8E108395BE00A3BC0C /* Debug */,
-                               1583EB8F108395BE00A3BC0C /* Release */,
+                               15D3082516F3E4DA00014F82 /* Debug */,
+                               15D3082616F3E4DA00014F82 /* Release */,
                        );
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
-               1583EBB3108395BE00A3BC0C /* Build configuration list for PBXNativeTarget "scutil-EmbeddedOther" */ = {
+               15D3082A16F3E4E100014F82 /* Build configuration list for PBXNativeTarget "SimulatorSupport.bundle-EmbeddedSimulator" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
-                               1583EBB4108395BE00A3BC0C /* Debug */,
-                               1583EBB5108395BE00A3BC0C /* Release */,
+                               15D3082B16F3E4E100014F82 /* Debug */,
+                               15D3082C16F3E4E100014F82 /* Release */,
                        );
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
-               15A5A2660D5B94190087BDA0 /* Build configuration list for PBXNativeTarget "SystemConfiguration.framework-EmbeddedSimulator" */ = {
+               15E1B05616EBAE3C00E5F06F /* Build configuration list for PBXNativeTarget "IPMonitor-EmbeddedSimulator" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
-                               15A5A2670D5B94190087BDA0 /* Debug */,
-                               15A5A2680D5B94190087BDA0 /* Release */,
+                               15E1B05716EBAE3C00E5F06F /* Debug */,
+                               15E1B05816EBAE3C00E5F06F /* Release */,
                        );
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
-               15C64A270F684C6B00D78394 /* Build configuration list for PBXAggregateTarget "configd_libSystem" */ = {
+               15E1B05E16EBAE7800E5F06F /* Build configuration list for PBXNativeTarget "IPMonitor.bundle-EmbeddedSimulator" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
-                               15C64A1F0F684C3300D78394 /* Debug */,
-                               15C64A200F684C3300D78394 /* Release */,
+                               15E1B05F16EBAE7800E5F06F /* Debug */,
+                               15E1B06016EBAE7800E5F06F /* Release */,
                        );
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
-               15C64A2B0F684C6B00D78394 /* Build configuration list for PBXAggregateTarget "configd_libSystem-Embedded" */ = {
+               15E83107167F9AF600FD51EC /* Build configuration list for PBXAggregateTarget "EVERYTHING" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
-                               15C64A2C0F684C6B00D78394 /* Debug */,
-                               15C64A2D0F684C6B00D78394 /* Release */,
+                               15E83105167F9AF600FD51EC /* Debug */,
+                               15E83106167F9AF600FD51EC /* Release */,
                        );
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
index 020e51afc7516ee92c8eff4ec36b46fa48298447..60be01a7582ce886e8c5002bd3c669a6d825d885 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2006, 2008, 2009, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2006, 2008, 2009, 2011-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -35,7 +35,7 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 
-#define        DNSINFO_VERSION         20111104
+#define        DNSINFO_VERSION         20130402
 
 #define DEFAULT_SEARCH_ORDER    200000   /* search order for the "default" resolver domain name */
 
@@ -73,13 +73,19 @@ typedef struct {
        DNS_VAR(uint32_t,               if_index);
        DNS_VAR(uint32_t,               flags);
        DNS_VAR(uint32_t,               reach_flags);   /* SCNetworkReachabilityFlags */
-       DNS_VAR(uint32_t,               reserved[5]);
+       DNS_VAR(uint32_t,               service_identifier);
+       DNS_VAR(uint32_t,               reserved[4]);
 } dns_resolver_t;
 #pragma pack()
 
 
-#define DNS_RESOLVER_FLAGS_SCOPED      1               /* configuration is for scoped questions */
+#define DNS_RESOLVER_FLAGS_SCOPED              1               /* configuration is for scoped questions */
+#define DNS_RESOLVER_FLAGS_REQUEST_A_RECORDS   2               /* always requesting for A dns records in queries */
+#define DNS_RESOLVER_FLAGS_REQUEST_AAAA_RECORDS        4               /* always requesting for AAAA dns records in queries */
+#define DNS_RESOLVER_FLAGS_SERVICE_SPECIFIC    8               /* configuration is service-specific */
 
+#define        DNS_RESOLVER_FLAGS_REQUEST_ALL_RECORDS  \
+       (DNS_RESOLVER_FLAGS_REQUEST_A_RECORDS | DNS_RESOLVER_FLAGS_REQUEST_AAAA_RECORDS)
 
 #pragma pack(4)
 typedef struct {
@@ -87,7 +93,9 @@ typedef struct {
        DNS_PTR(dns_resolver_t **,      resolver);
        DNS_VAR(int32_t,                n_scoped_resolver);     /* "scoped" resolver configurations */
        DNS_PTR(dns_resolver_t **,      scoped_resolver);
-       DNS_VAR(uint32_t,               reserved[5]);
+       DNS_VAR(uint64_t,               generation);
+       DNS_VAR(int32_t,                n_service_specific_resolver);
+       DNS_PTR(dns_resolver_t **,      service_specific_resolver);
 } dns_config_t;
 #pragma pack()
 
index 26b1e9de3f17a3eed069fc0532f12c796c4d18e9..ee0a17a7501a3c2672ac9928a747758547c8f2fc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2006, 2008-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2004, 2006, 2008-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #include <pthread.h>
 #include <mach/mach.h>
 #include <mach/mach_error.h>
+#include <dispatch/dispatch.h>
+#include <xpc/xpc.h>
 
+#include "libSystemConfiguration_client.h"
 #include "dnsinfo.h"
 #include "dnsinfo_private.h"
-#include "shared_dns_info.h"
-#include "network_information_priv.h"
-
-
-static pthread_once_t  _dns_initialized        = PTHREAD_ONCE_INIT;
-static pthread_mutex_t _dns_lock               = PTHREAD_MUTEX_INITIALIZER;
-static mach_port_t     _dns_server             = MACH_PORT_NULL;
-
-enum {
-       get_dns_info    = 1,
-       get_nwi_state   = 2,
-};
 
 typedef uint32_t getflags;
 
-static void
-__dns_fork_handler()
-{
-       // the process has forked (and we are the child process)
-       _dns_server = MACH_PORT_NULL;
-       return;
-}
-
-
-static void
-__dns_initialize(void)
-{
-       // add handler to cleanup after fork()
-       (void) pthread_atfork(NULL, NULL, __dns_fork_handler);
-
-       return;
-}
-
-
 static boolean_t
 add_list(void **padding, uint32_t *n_padding, int32_t count, int32_t size, void **list)
 {
@@ -90,138 +62,6 @@ add_list(void **padding, uint32_t *n_padding, int32_t count, int32_t size, void
 #define        DNS_CONFIG_BUF_MAX      1024*1024
 
 
-static kern_return_t
-_dns_server_copy(void* dataRef, mach_msg_type_number_t* dataLen, getflags flags){
-       mach_port_t     server;
-       kern_return_t   status  = KERN_FAILURE;
-
-       // initialize runtime
-       pthread_once(&_dns_initialized, __dns_initialize);
-
-       // open a new session with the DNS configuration server
-       server = _dns_server;
-       while (TRUE) {
-               if (server != MACH_PORT_NULL) {
-                       if (flags == get_dns_info) {
-                               status = shared_dns_infoGet(server, dataRef, dataLen);
-                       } else {
-                               status = shared_nwi_stateGet(server, dataRef, dataLen);
-                       }
-                       if (status == KERN_SUCCESS) {
-                               break;
-                       }
-
-                       // our [cached] server port is not valid
-                       if ((status != MACH_SEND_INVALID_DEST) && (status != MIG_SERVER_DIED)) {
-                               // if we got an unexpected error, don't retry
-                               fprintf(stderr,
-                                       "dns_configuration_copy shared_dns_infoGet(): %s\n",
-                                       mach_error_string(status));
-                               break;
-                       }
-               }
-
-               pthread_mutex_lock(&_dns_lock);
-               if (_dns_server != MACH_PORT_NULL) {
-                       if (server == _dns_server) {
-                               // if the server we tried returned the error
-                               (void)mach_port_deallocate(mach_task_self(), server);
-                               _dns_server = _dns_configuration_server_port();
-                       } else {
-                               // another thread has refreshed the DNS server port
-                       }
-               } else {
-                       _dns_server = _dns_configuration_server_port();
-               }
-               server = _dns_server;
-               pthread_mutex_unlock(&_dns_lock);
-
-               if (server == MACH_PORT_NULL) {
-                       // if server not available
-                       break;
-               }
-       }
-
-       return status;
-}
-
-
-__private_extern__
-nwi_state*
-_nwi_state_copy() {
-       dnsDataOut_t            dataRef         = NULL;
-       mach_msg_type_number_t  dataLen         = 0;
-       kern_return_t           status;
-       nwi_state*              state           = NULL;
-
-       status = _dns_server_copy(&dataRef, &dataLen, get_nwi_state);
-       if (status != KERN_SUCCESS) {
-               return NULL;
-       }
-
-       if (dataRef != NULL) {
-               state = malloc(dataLen);
-               if (state == NULL) {
-                       vm_deallocate(mach_task_self(), (vm_address_t)dataRef,
-                                     dataLen);
-                       return NULL;
-               }
-               memcpy((void*) state, (void*) dataRef, dataLen);
-               state->ref = 0;
-               status = vm_deallocate(mach_task_self(), (vm_address_t)dataRef, dataLen);
-               if (status != KERN_SUCCESS) {
-                       mach_error("vm_deallocate():", status);
-                       free(state);
-                       return NULL;
-               }
-       }
-
-       return state;
-}
-
-
-static _dns_config_buf_t *
-copy_dns_info()
-{
-       uint8_t                 *buf    = NULL;
-       dnsDataOut_t            dataRef = NULL;
-       mach_msg_type_number_t  dataLen = 0;
-       kern_return_t           status;
-
-       status = _dns_server_copy(&dataRef, &dataLen, get_dns_info);
-       if (status != KERN_SUCCESS) {
-               return NULL;
-       }
-
-       if (dataRef != NULL) {
-               if ((dataLen >= sizeof(_dns_config_buf_t)) && (dataLen <= DNS_CONFIG_BUF_MAX)) {
-                       /* ALIGN: cast okay since _dns_config_buf_t is int aligned */
-                       _dns_config_buf_t       *config         = (_dns_config_buf_t *)(void *)dataRef;
-                       uint32_t                n_padding       = ntohl(config->n_padding);
-
-                       if (n_padding <= (DNS_CONFIG_BUF_MAX - dataLen)) {
-                               uint32_t        len;
-
-                               len = dataLen + n_padding;
-                               buf = malloc(len);
-                               bcopy((void *)dataRef, buf, dataLen);
-                               bzero(&buf[dataLen], n_padding);
-                       }
-               }
-
-               status = vm_deallocate(mach_task_self(), (vm_address_t)dataRef, dataLen);
-               if (status != KERN_SUCCESS) {
-                       mach_error("vm_deallocate():", status);
-                       free(buf);
-                       return NULL;
-               }
-       }
-
-       /* ALIGN: buf malloc'ed, should be aligned >8 bytes */
-       return (_dns_config_buf_t *)(void *)buf;
-}
-
-
 static dns_resolver_t *
 expand_resolver(_dns_resolver_buf_t *buf, uint32_t n_buf, void **padding, uint32_t *n_padding)
 {
@@ -293,6 +133,10 @@ expand_resolver(_dns_resolver_buf_t *buf, uint32_t n_buf, void **padding, uint32
 
        resolver->if_index = ntohl(resolver->if_index);
 
+       // initialize service_identifier
+
+       resolver->service_identifier = ntohl(resolver->service_identifier);
+
        // initialize flags
 
        resolver->flags = ntohl(resolver->flags);
@@ -311,7 +155,7 @@ expand_resolver(_dns_resolver_buf_t *buf, uint32_t n_buf, void **padding, uint32
        }
 
        while (n_attribute >= sizeof(dns_attribute_t)) {
-               int32_t attribute_length        = ntohl(attribute->length);
+               uint32_t        attribute_length        = ntohl(attribute->length);
 
                switch (ntohl(attribute->type)) {
                        case RESOLVER_ATTRIBUTE_DOMAIN :
@@ -365,6 +209,7 @@ expand_config(_dns_config_buf_t *buf)
        uint32_t                n_padding;
        int32_t                 n_resolver              = 0;
        int32_t                 n_scoped_resolver       = 0;
+       int32_t                 n_service_specific_resolver     = 0;
        void                    *padding;
 
        // establish padding
@@ -392,6 +237,15 @@ expand_config(_dns_config_buf_t *buf)
                goto error;
        }
 
+       config->n_service_specific_resolver = ntohl(config->n_service_specific_resolver);
+       if (!add_list(&padding,
+                     &n_padding,
+                     config->n_service_specific_resolver,
+                     sizeof(DNS_PTR(dns_resolver_t *, x)),
+                     (void **)&config->service_specific_resolver)) {
+               goto error;
+       }
+
        // process configuration buffer "attribute" data
 
        n_attribute = ntohl(buf->n_attribute);
@@ -403,7 +257,8 @@ expand_config(_dns_config_buf_t *buf)
 
                switch (attribute_type) {
                        case CONFIG_ATTRIBUTE_RESOLVER :
-                       case CONFIG_ATTRIBUTE_SCOPED_RESOLVER   : {
+                       case CONFIG_ATTRIBUTE_SCOPED_RESOLVER   :
+                       case CONFIG_ATTRIBUTE_SERVICE_SPECIFIC_RESOLVER : {
                                dns_resolver_t  *resolver;
 
                                // expand resolver buffer
@@ -420,8 +275,10 @@ expand_config(_dns_config_buf_t *buf)
 
                                if (attribute_type == CONFIG_ATTRIBUTE_RESOLVER) {
                                        config->resolver[n_resolver++] = resolver;
-                               } else {
+                               } else if (attribute_type == CONFIG_ATTRIBUTE_SCOPED_RESOLVER) {
                                        config->scoped_resolver[n_scoped_resolver++] = resolver;
+                               } else if (attribute_type == CONFIG_ATTRIBUTE_SERVICE_SPECIFIC_RESOLVER) {
+                                       config->service_specific_resolver[n_service_specific_resolver++] = resolver;
                                }
 
                                break;
@@ -443,6 +300,10 @@ expand_config(_dns_config_buf_t *buf)
                goto error;
        }
 
+       if (n_service_specific_resolver != config->n_service_specific_resolver) {
+               goto error;
+       }
+
        return config;
 
     error :
@@ -456,29 +317,124 @@ dns_configuration_notify_key()
 {
        const char      *key;
 
-       // initialize runtime
-       pthread_once(&_dns_initialized, __dns_initialize);
-
-       key = _dns_configuration_notify_key();
+#if    !TARGET_IPHONE_SIMULATOR
+       key = "com.apple.system.SystemConfiguration.dns_configuration";
+#else  // !TARGET_IPHONE_SIMULATOR
+       key = "com.apple.iOS_Simulator.SystemConfiguration.dns_configuration";
+#endif // !TARGET_IPHONE_SIMULATOR
        return key;
 }
 
 
+#pragma mark -
+#pragma mark DNS configuration [dnsinfo] client support
+
+
+// Note: protected by __dns_configuration_queue()
+static int                     dnsinfo_active  = 0;
+static libSC_info_client_t     *dnsinfo_client = NULL;
+
+
+static dispatch_queue_t
+__dns_configuration_queue()
+{
+       static dispatch_once_t  once;
+       static dispatch_queue_t q;
+
+       dispatch_once(&once, ^{
+               q = dispatch_queue_create(DNSINFO_SERVICE_NAME, NULL);
+       });
+
+       return q;
+}
+
+
 dns_config_t *
 dns_configuration_copy()
 {
-       _dns_config_buf_t       *buf;
-       dns_config_t            *config;
+       uint8_t                 *buf            = NULL;
+       dns_config_t            *config         = NULL;
+       static const char       *proc_name      = NULL;
+       xpc_object_t            reqdict;
+       xpc_object_t            reply;
+
+       dispatch_sync(__dns_configuration_queue(), ^{
+               if ((dnsinfo_active++ == 0) || (dnsinfo_client == NULL)) {
+                       static dispatch_once_t  once;
+                       static const char       *service_name   = DNSINFO_SERVICE_NAME;
+
+                       dispatch_once(&once, ^{
+                               const char      *name;
+
+                               // get [XPC] service name
+                               name = getenv(service_name);
+                               if ((name != NULL) && (issetugid() == 0)) {
+                                       service_name = strdup(name);
+                               }
+
+                               // get process name
+                               proc_name = getprogname();
+                       });
 
-       buf = copy_dns_info();
-       if (buf == NULL) {
+                       dnsinfo_client =
+                               libSC_info_client_create(__dns_configuration_queue(),   // dispatch queue
+                                                        service_name,                  // XPC service name
+                                                        "DNS configuration");          // service description
+                       if (dnsinfo_client == NULL) {
+                               --dnsinfo_active;
+                       }
+               }
+       });
+
+       if ((dnsinfo_client == NULL) || !dnsinfo_client->active) {
+               // if DNS configuration server not available
                return NULL;
        }
 
-       config = expand_config(buf);
-       if (config == NULL) {
-               free(buf);
-               return NULL;
+       // create message
+       reqdict = xpc_dictionary_create(NULL, NULL, 0);
+
+       // set process name
+       if (proc_name != NULL) {
+               xpc_dictionary_set_string(reqdict, DNSINFO_PROC_NAME, proc_name);
+       }
+
+       // set request
+       xpc_dictionary_set_int64(reqdict, DNSINFO_REQUEST, DNSINFO_REQUEST_COPY);
+
+       // send request to the DNS configuration server
+       reply = libSC_send_message_with_reply_sync(dnsinfo_client, reqdict);
+       xpc_release(reqdict);
+
+       if (reply != NULL) {
+               const void      *dataRef;
+               size_t          dataLen = 0;
+
+               dataRef = xpc_dictionary_get_data(reply, DNSINFO_CONFIGURATION, &dataLen);
+               if ((dataRef != NULL) &&
+                   ((dataLen >= sizeof(_dns_config_buf_t)) && (dataLen <= DNS_CONFIG_BUF_MAX))) {
+                       _dns_config_buf_t       *config         = (_dns_config_buf_t *)(void *)dataRef;
+                       uint32_t                n_padding       = ntohl(config->n_padding);
+
+                       if (n_padding <= (DNS_CONFIG_BUF_MAX - dataLen)) {
+                               uint32_t        len;
+
+                               len = dataLen + n_padding;
+                               buf = malloc(len);
+                               bcopy((void *)dataRef, buf, dataLen);
+                               bzero(&buf[dataLen], n_padding);
+                       }
+               }
+
+               xpc_release(reply);
+       }
+
+       if (buf != NULL) {
+               /* ALIGN: cast okay since _dns_config_buf_t is int aligned */
+               config = expand_config((_dns_config_buf_t *)(void *)buf);
+               if (config == NULL) {
+                       free(buf);
+               }
        }
 
        return config;
@@ -489,9 +445,17 @@ void
 dns_configuration_free(dns_config_t *config)
 {
        if (config == NULL) {
-               return;
+               return; // ASSERT
        }
 
+       dispatch_sync(__dns_configuration_queue(), ^{
+               if (--dnsinfo_active == 0) {
+                       // if last reference, drop connection
+                       libSC_info_client_release(dnsinfo_client);
+                       dnsinfo_client = NULL;
+               }
+       });
+
        free((void *)config);
        return;
 }
@@ -500,6 +464,34 @@ dns_configuration_free(dns_config_t *config)
 void
 _dns_configuration_ack(dns_config_t *config, const char *bundle_id)
 {
+       xpc_object_t    reqdict;
+
+       if (config == NULL) {
+               return; // ASSERT
+       }
+
+       if ((dnsinfo_client == NULL) || !dnsinfo_client->active) {
+               // if DNS configuration server not available
+               return;
+       }
+
+       dispatch_sync(__dns_configuration_queue(), ^{
+               dnsinfo_active++;       // keep connection active (for the life of the process)
+       });
+
+       // create message
+       reqdict = xpc_dictionary_create(NULL, NULL, 0);
+
+       // set request
+       xpc_dictionary_set_int64(reqdict, DNSINFO_REQUEST, DNSINFO_REQUEST_ACKNOWLEDGE);
+
+       // set generation
+       xpc_dictionary_set_uint64(reqdict, DNSINFO_GENERATION, config->generation);
+
+       // send acknowledgement to the DNS configuration server
+       xpc_connection_send_message(dnsinfo_client->connection, reqdict);
+
+       xpc_release(reqdict);
        return;
 }
 
@@ -512,7 +504,7 @@ main(int argc, char **argv)
 
        config = dns_configuration_copy();
        if (config != NULL) {
-               dns_configuration_free(&config);
+               dns_configuration_free(config);
        }
 
        exit(0);
index db361d5931fe1bc8ea279770560d0a14a00e89bb..9bc5499f839fe143304c9a96ce017e8a33fa5e64 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2006, 2009, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2004, 2006, 2009, 2011-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #include <strings.h>
 #include <mach/mach.h>
 #include <mach/mach_error.h>
+#include <mach/mach_time.h>
 #include <CommonCrypto/CommonDigest.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCPrivate.h>
 
 #include "dnsinfo_create.h"
 #include "dnsinfo_private.h"
-#include "shared_dns_info.h"
 #include "network_information_priv.h"
 
+#include "ip_plugin.h"
+
 
 #define ROUNDUP(a, size) \
        (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a))
  */
 
 
+__private_extern__
 dns_create_config_t
 _dns_configuration_create()
 {
        _dns_config_buf_t       *config;
 
        config = calloc(1, INITIAL_CONFIGURATION_BUF_SIZE);
+       config->config.generation = mach_absolute_time();
 //     config->n_attribute = 0;
 //     config->n_padding = 0;
        return (dns_create_config_t)config;
@@ -111,6 +118,11 @@ config_add_attribute(dns_create_config_t   *_config,
 }
 
 
+static void
+_dns_resolver_set_reach_flags(dns_create_resolver_t _resolver);
+
+
+__private_extern__
 void
 _dns_configuration_add_resolver(dns_create_config_t     *_config,
                                dns_create_resolver_t   _resolver)
@@ -119,6 +131,11 @@ _dns_configuration_add_resolver(dns_create_config_t     *_config,
        uint32_t                padding         = 0;
        _dns_resolver_buf_t     *resolver       = (_dns_resolver_buf_t *)_resolver;
 
+       /*
+        * add reachability flags for this resovler configuration
+        */
+       _dns_resolver_set_reach_flags(_resolver);
+
        /*
         * compute the amount of space that will be needed for
         * pointers to the resolver, the nameservers, the search
@@ -135,17 +152,24 @@ _dns_configuration_add_resolver(dns_create_config_t     *_config,
                padding += ntohl(resolver->resolver.n_sortaddr) * sizeof(DNS_PTR(dns_sortaddr_t *, x));
        }
 
-       if ((ntohl(resolver->resolver.flags) & DNS_RESOLVER_FLAGS_SCOPED) == 0) {
-               config->config.n_resolver = htonl(ntohl(config->config.n_resolver) + 1);
+       if ((ntohl(resolver->resolver.flags) & DNS_RESOLVER_FLAGS_SCOPED)) {
+               config->config.n_scoped_resolver = htonl(ntohl(config->config.n_scoped_resolver) + 1);
                config_add_attribute(_config,
-                                    CONFIG_ATTRIBUTE_RESOLVER,
+                                    CONFIG_ATTRIBUTE_SCOPED_RESOLVER,
+                                    sizeof(_dns_resolver_buf_t) + ntohl(resolver->n_attribute),
+                                    (void *)resolver,
+                                    padding);
+       } else if ((ntohl(resolver->resolver.flags) & DNS_RESOLVER_FLAGS_SERVICE_SPECIFIC)) {
+               config->config.n_service_specific_resolver = htonl(ntohl(config->config.n_service_specific_resolver) + 1);
+               config_add_attribute(_config,
+                                    CONFIG_ATTRIBUTE_SERVICE_SPECIFIC_RESOLVER,
                                     sizeof(_dns_resolver_buf_t) + ntohl(resolver->n_attribute),
                                     (void *)resolver,
                                     padding);
        } else {
-               config->config.n_scoped_resolver = htonl(ntohl(config->config.n_scoped_resolver) + 1);
+               config->config.n_resolver = htonl(ntohl(config->config.n_resolver) + 1);
                config_add_attribute(_config,
-                                    CONFIG_ATTRIBUTE_SCOPED_RESOLVER,
+                                    CONFIG_ATTRIBUTE_RESOLVER,
                                     sizeof(_dns_resolver_buf_t) + ntohl(resolver->n_attribute),
                                     (void *)resolver,
                                     padding);
@@ -154,31 +178,8 @@ _dns_configuration_add_resolver(dns_create_config_t     *_config,
        return;
 }
 
-_Bool
-_nwi_state_store(nwi_state* state)
-{
-       mach_port_t             server;
-       kern_return_t           status;
-       dnsDataOut_t            dataRef = (dnsDataOut_t) state;
-       mach_msg_type_number_t  dataLen = state->size;
-
-       server = _dns_configuration_server_port();
-       if (server == MACH_PORT_NULL) {
-               return FALSE;
-       }
-
-       status = shared_nwi_stateSet(server, dataRef, dataLen);
-
-       (void) mach_port_deallocate(mach_task_self(), server);
-
-       if (status != KERN_SUCCESS) {
-               return FALSE;
-       }
-
-       return TRUE;
-}
-
 
+__private_extern__
 void
 _dns_configuration_signature(dns_create_config_t       *_config,
                             unsigned char              *signature,
@@ -191,9 +192,13 @@ _dns_configuration_signature(dns_create_config_t   *_config,
 
                if (config != NULL) {
                        CC_SHA1_CTX     ctx;
+                       uint64_t        generation_save;
                        unsigned char   *sha1;
                        unsigned char   sha1_buf[CC_SHA1_DIGEST_LENGTH];
 
+                       generation_save = config->config.generation;
+                       config->config.generation = 0;
+
                        sha1 = (signature_len >= CC_SHA1_DIGEST_LENGTH) ? signature : sha1_buf;
                        CC_SHA1_Init(&ctx);
                        CC_SHA1_Update(&ctx,
@@ -203,46 +208,16 @@ _dns_configuration_signature(dns_create_config_t  *_config,
                        if (sha1 != signature) {
                                bcopy(sha1, signature, signature_len);
                        }
-               }
-       }
-
-       return;
-}
-
-
-_Bool
-_dns_configuration_store(dns_create_config_t *_config)
-{
-       dnsDataOut_t            dataRef = NULL;
-       mach_msg_type_number_t  dataLen = 0;
-       mach_port_t             server;
-       kern_return_t           status;
-
-       server = _dns_configuration_server_port();
-       if (server == MACH_PORT_NULL) {
-               return FALSE;
-       }
-
-       if (_config != NULL) {
-               _dns_config_buf_t       *config = (_dns_config_buf_t *)*_config;
 
-               if (config != NULL) {
-                       dataRef = (dnsDataOut_t)config;
-                       dataLen = sizeof(_dns_config_buf_t) + ntohl(config->n_attribute);
+                       config->config.generation = generation_save;
                }
        }
 
-       status = shared_dns_infoSet(server, dataRef, dataLen);
-       (void) mach_port_deallocate(mach_task_self(), server);
-       if (status != KERN_SUCCESS) {
-               mach_error("shared_dns_infoSet():", status);
-               return FALSE;
-       }
-
-       return TRUE;
+       return;
 }
 
 
+__private_extern__
 void
 _dns_configuration_free(dns_create_config_t *_config)
 {
@@ -258,6 +233,7 @@ _dns_configuration_free(dns_create_config_t *_config)
  * DNS resolver configuration functions
  */
 
+__private_extern__
 dns_create_resolver_t
 _dns_resolver_create()
 {
@@ -296,7 +272,7 @@ _dns_resolver_add_attribute(dns_create_resolver_t   *_resolver,
 
        // add attribute [header]
 
-       /* ALIGN: _dns_config_buf_t is int aligned */
+       /* ALIGN: _dns_resolver_buf_t is int aligned */
        header = (dns_attribute_t *)(void *)&resolver->attribute[oldLen];
        header->type   = htonl(attribute_type);
        header->length = htonl(newLen);
@@ -313,17 +289,44 @@ _dns_resolver_add_attribute(dns_create_resolver_t *_resolver,
 }
 
 
+__private_extern__
 void
 _dns_resolver_add_nameserver(dns_create_resolver_t *_resolver, struct sockaddr *nameserver)
 {
+       uint32_t                new_flags       = 0;
+       uint32_t                old_flags;
        _dns_resolver_buf_t     *resolver       = (_dns_resolver_buf_t *)*_resolver;
 
+       old_flags = ntohl(resolver->resolver.flags);
+
+       switch (nameserver->sa_family) {
+               case AF_INET:
+                       if (ntohl(((struct sockaddr_in*)(void *)nameserver)->sin_addr.s_addr) == INADDR_LOOPBACK) {
+                               new_flags = DNS_RESOLVER_FLAGS_REQUEST_ALL_RECORDS;
+                       }
+                       break;
+               case AF_INET6:
+                       if (IN6_IS_ADDR_LOOPBACK(&((struct sockaddr_in6 *)(void *)nameserver)->sin6_addr)){
+                               new_flags = DNS_RESOLVER_FLAGS_REQUEST_ALL_RECORDS;
+                       }
+                       break;
+               default:
+                       break;
+       }
+
        resolver->resolver.n_nameserver = htonl(ntohl(resolver->resolver.n_nameserver) + 1);
        _dns_resolver_add_attribute(_resolver, RESOLVER_ATTRIBUTE_ADDRESS, nameserver->sa_len, (void *)nameserver);
+
+       if (new_flags != 0) {
+               // if DNS request flags not explicitly set and we are
+               // adding a LOOPBACK resolver address
+               _dns_resolver_set_flags(_resolver, old_flags | new_flags);
+       }
        return;
 }
 
 
+__private_extern__
 void
 _dns_resolver_add_search(dns_create_resolver_t *_resolver, const char *search)
 {
@@ -335,6 +338,7 @@ _dns_resolver_add_search(dns_create_resolver_t *_resolver, const char *search)
 }
 
 
+__private_extern__
 void
 _dns_resolver_add_sortaddr(dns_create_resolver_t *_resolver, dns_sortaddr_t *sortaddr)
 {
@@ -346,6 +350,7 @@ _dns_resolver_add_sortaddr(dns_create_resolver_t *_resolver, dns_sortaddr_t *sor
 }
 
 
+__private_extern__
 void
 _dns_resolver_set_domain(dns_create_resolver_t *_resolver, const char *domain)
 {
@@ -354,6 +359,7 @@ _dns_resolver_set_domain(dns_create_resolver_t *_resolver, const char *domain)
 }
 
 
+__private_extern__
 void
 _dns_resolver_set_flags(dns_create_resolver_t *_resolver, uint32_t flags)
 {
@@ -364,6 +370,7 @@ _dns_resolver_set_flags(dns_create_resolver_t *_resolver, uint32_t flags)
 }
 
 
+__private_extern__
 void
 _dns_resolver_set_if_index(dns_create_resolver_t *_resolver, uint32_t if_index)
 {
@@ -374,6 +381,7 @@ _dns_resolver_set_if_index(dns_create_resolver_t *_resolver, uint32_t if_index)
 }
 
 
+__private_extern__
 void
 _dns_resolver_set_options(dns_create_resolver_t *_resolver, const char *options)
 {
@@ -382,6 +390,7 @@ _dns_resolver_set_options(dns_create_resolver_t *_resolver, const char *options)
 }
 
 
+__private_extern__
 void
 _dns_resolver_set_order(dns_create_resolver_t *_resolver, uint32_t order)
 {
@@ -392,6 +401,7 @@ _dns_resolver_set_order(dns_create_resolver_t *_resolver, uint32_t order)
 }
 
 
+__private_extern__
 void
 _dns_resolver_set_port(dns_create_resolver_t *_resolver, uint16_t port)
 {
@@ -402,16 +412,124 @@ _dns_resolver_set_port(dns_create_resolver_t *_resolver, uint16_t port)
 }
 
 
-void
-_dns_resolver_set_reach_flags(dns_create_resolver_t *_resolver, uint32_t reach_flags)
+/*
+ * rankReachability()
+ *   Not reachable       == 0
+ *   Connection Required == 1
+ *   Reachable           == 2
+ */
+static int
+rankReachability(SCNetworkReachabilityFlags flags)
 {
-       _dns_resolver_buf_t     *resolver       = (_dns_resolver_buf_t *)*_resolver;
+       int     rank = 0;
+
+       if (flags & kSCNetworkReachabilityFlagsReachable)               rank = 2;
+       if (flags & kSCNetworkReachabilityFlagsConnectionRequired)      rank = 1;
+       return rank;
+}
+
+
+static void
+_dns_resolver_set_reach_flags(dns_create_resolver_t _resolver)
+{
+       _dns_resolver_buf_t     *resolver       = (_dns_resolver_buf_t *)_resolver;
+
+       if (resolver->resolver.n_nameserver != 0) {
+               dns_attribute_t                 *attribute;
+               SCNetworkReachabilityFlags      flags           = kSCNetworkReachabilityFlagsReachable;
+               uint32_t                        n_attribute;
+               uint32_t                        n_nameserver    = 0;
+               CFMutableDictionaryRef          targetOptions;
+
+               targetOptions = CFDictionaryCreateMutable(NULL,
+                                                         0,
+                                                         &kCFTypeDictionaryKeyCallBacks,
+                                                         &kCFTypeDictionaryValueCallBacks);
+               CFDictionarySetValue(targetOptions,
+                                    kSCNetworkReachabilityOptionServerBypass,
+                                    kCFBooleanTrue);
+               if (resolver->resolver.if_index != 0) {
+                       char            if_name[IFNAMSIZ];
+
+                       if (if_indextoname(ntohl(resolver->resolver.if_index), if_name) != NULL) {
+                               CFStringRef     targetInterface;
+
+                               targetInterface = CFStringCreateWithCString(NULL,
+                                                                           if_name,
+                                                                           kCFStringEncodingASCII);
+                               CFDictionarySetValue(targetOptions,
+                                                    kSCNetworkReachabilityOptionInterface,
+                                                    targetInterface);
+                               CFRelease(targetInterface);
+                       }
+               }
+
+               attribute   = (dns_attribute_t *)(void *)&resolver->attribute[0];
+               n_attribute = ntohl(resolver->n_attribute);
+
+               while (n_attribute >= sizeof(dns_attribute_t)) {
+                       uint32_t        attribute_length        = ntohl(attribute->length);
+                       uint32_t        attribute_type          = ntohl(attribute->type);
+
+                       if (attribute_type == RESOLVER_ATTRIBUTE_ADDRESS) {
+                               struct sockaddr                 *addr;
+                               CFDataRef                       addrData;
+                               SCNetworkReachabilityFlags      ns_flags;
+                               Boolean                         ok;
+                               SCNetworkReachabilityRef        target;
+
+                               addr = (struct sockaddr *)&attribute->attribute[0];
+                               addrData = CFDataCreate(NULL, (const UInt8 *)addr, addr->sa_len);
+                               CFDictionarySetValue(targetOptions,
+                                                    kSCNetworkReachabilityOptionRemoteAddress,
+                                                    addrData);
+                               CFRelease(addrData);
+
+                               target = SCNetworkReachabilityCreateWithOptions(NULL, targetOptions);
+                               if (target == NULL) {
+                                       CFDictionaryRemoveValue(targetOptions, kSCNetworkReachabilityOptionInterface);
+                                       target = SCNetworkReachabilityCreateWithOptions(NULL, targetOptions);
+                                       if (target != NULL) {
+                                               // if interface name not (no longer) valid
+                                               CFRelease(target);
+                                               flags = 0;
+                                               break;
+                                       }
+
+                                       // address not valid?
+                                       my_log(LOG_ERR,
+                                              "_dns_resolver_set_reach_flags SCNetworkReachabilityCreateWithOptions() failed:\n  options = %@",
+                                              targetOptions);
+                                       break;
+                               }
+
+                               ok = SCNetworkReachabilityGetFlags(target, &ns_flags);
+                               CFRelease(target);
+                               if (!ok) {
+                                       break;
+                               }
+
+                               if ((n_nameserver++ == 0) ||
+                                   (rankReachability(ns_flags) < rankReachability(flags))) {
+                                       /* return the first (and later, worst case) result */
+                                       flags = ns_flags;
+                               }
+                       }
+
+                       attribute   = (dns_attribute_t *)((void *)attribute + attribute_length);
+                       n_attribute -= attribute_length;
+               }
+
+               CFRelease(targetOptions);
+
+               resolver->resolver.reach_flags = htonl(flags);
+       }
 
-       resolver->resolver.reach_flags = htonl(reach_flags);
        return;
 }
 
 
+__private_extern__
 void
 _dns_resolver_set_timeout(dns_create_resolver_t *_resolver, uint32_t timeout)
 {
@@ -422,6 +540,17 @@ _dns_resolver_set_timeout(dns_create_resolver_t *_resolver, uint32_t timeout)
 }
 
 
+__private_extern__
+void
+_dns_resolver_set_service_identifier(dns_create_resolver_t *_resolver, uint32_t service_identifier)
+{
+       _dns_resolver_buf_t *resolver   = (_dns_resolver_buf_t *)*_resolver;
+
+       resolver->resolver.service_identifier = htonl(service_identifier);
+}
+
+
+__private_extern__
 void
 _dns_resolver_free(dns_create_resolver_t *_resolver)
 {
index 89c71b53911b2dd1543ad6e722331a5589f73ecd..decc575d100218c31b1b6ac371d6f649273c1f57 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2006, 2008, 2009, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2006, 2008, 2009, 2011-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -49,110 +49,86 @@ typedef const struct __dns_create_resolver *    dns_create_resolver_t;
 
 __BEGIN_DECLS
 
-/*
- * NOTE: __private_extern__ and __OSX_AVAILABLE_STARTING() cannot be mixed
- *       due to a "visibility" conflict
- */
-
 /*
  * DNS configuration creation APIs
  */
-__private_extern__
 dns_create_config_t
-_dns_configuration_create       (void)                                         /*__OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0)*/;
+_dns_configuration_create       (void)                                         __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0);
 
-__private_extern__
 void
 _dns_configuration_add_resolver (dns_create_config_t   *_config,
-                                dns_create_resolver_t  _resolver)              /*__OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0)*/;
+                                dns_create_resolver_t  _resolver)              __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0);
 
-__private_extern__
 void
 _dns_configuration_signature   (dns_create_config_t    *_config,
                                 unsigned char          *signature,
-                                size_t                 signature_len)          /*__OSX_AVAILABLE_STARTING(__MAC_10_7+,__IPHONE_5_0)*/; // signature_len >= CC_SHA1_DIGEST_LENGTH
-
-__private_extern__
-_Bool
-_dns_configuration_store       (dns_create_config_t    *_config)               /*__OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0)*/;
+                                size_t                 signature_len)          __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_5_0);      // signature_len >= CC_SHA1_DIGEST_LENGTH
 
-__private_extern__
 void
-_dns_configuration_free                (dns_create_config_t    *_config)               /*__OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0)*/;
+_dns_configuration_free                (dns_create_config_t    *_config)               __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0);
 
 /*
  * DNS [resolver] configuration creation APIs
  */
-__private_extern__
 dns_create_resolver_t
-_dns_resolver_create           (void)                                          /*__OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0)*/;
+_dns_resolver_create           (void)                                          __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0);
 
-__private_extern__
 void
 _dns_resolver_set_domain       (dns_create_resolver_t  *_resolver,
-                                const char             *domain)                /*__OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0)*/;
+                                const char             *domain)                __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0);
 
-__private_extern__
 void
 _dns_resolver_add_nameserver   (dns_create_resolver_t  *_resolver,
-                                struct sockaddr        *nameserver)            /*__OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0)*/;
+                                struct sockaddr        *nameserver)            __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0);
 
-__private_extern__
 void
 _dns_resolver_add_search       (dns_create_resolver_t  *_resolver,
-                                const char             *search)                /*__OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0)*/;
+                                const char             *search)                __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0);
 
-__private_extern__
 void
 _dns_resolver_add_sortaddr     (dns_create_resolver_t  *_resolver,
-                                dns_sortaddr_t         *sortaddr)              /*__OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0)*/;
+                                dns_sortaddr_t         *sortaddr)              __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0);
 
-__private_extern__
 void
 _dns_resolver_set_flags                (dns_create_resolver_t  *_resolver,
-                                uint32_t               flags)                  /*__OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_4_0)*/;
+                                uint32_t               flags)                  __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_4_0);
 
-__private_extern__
 void
 _dns_resolver_set_if_index     (dns_create_resolver_t  *_resolver,
-                                uint32_t               if_index)               /*__OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_4_0)*/;
+                                uint32_t               if_index)               __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_4_0);
 
-__private_extern__
 void
 _dns_resolver_set_options      (dns_create_resolver_t  *_resolver,
-                                const char             *options)               /*__OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0)*/;
+                                const char             *options)               __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0);
 
-__private_extern__
 void
 _dns_resolver_set_order                (dns_create_resolver_t  *_resolver,
-                                uint32_t               order)                  /*__OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0)*/;
+                                uint32_t               order)                  __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0);
 
-__private_extern__
 void
 _dns_resolver_set_port         (dns_create_resolver_t  *_resolver,
-                                uint16_t               port)                   /*__OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0)*/;  // host byte order
+                                uint16_t               port)                   __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0);      // host byte order
 
-__private_extern__
 void
-_dns_resolver_set_reach_flags  (dns_create_resolver_t  *_resolver,
-                                uint32_t               reach_flags)            /*__OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_5_0)*/;
+_dns_resolver_set_timeout      (dns_create_resolver_t  *_resolver,
+                                uint32_t               timeout)                __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0);
 
-__private_extern__
 void
-_dns_resolver_set_timeout      (dns_create_resolver_t  *_resolver,
-                                uint32_t               timeout)                /*__OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0)*/;
+_dns_resolver_set_service_identifier   (dns_create_resolver_t  *_resolver,
+                                       uint32_t                service_identifier)     __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
 
-__private_extern__
 void
-_dns_resolver_free             (dns_create_resolver_t  *_resolver)             /*__OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0)*/;
+_dns_resolver_free             (dns_create_resolver_t  *_resolver)             __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0);
 
 #if    !TARGET_OS_IPHONE
 /*
  * DNS [resolver] flat-file configuration creation APIs
  */
-__private_extern__
 void
-_dnsinfo_flatfile_add_resolvers        (dns_create_config_t    *config)                /*__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)*/;
+_dnsinfo_flatfile_add_resolvers        (dns_create_config_t    *config)                __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA);
+
+void
+_dnsinfo_flatfile_set_flags    (uint32_t               flags)                  __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_NA);
 #endif // !TARGET_OS_IPHONE
 
 __END_DECLS
index e052d2eb543f1ffb0a4d9d13271965864fcef395..65861b7914542e432d6bb3e4bb809feabd6261b4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2009, 2011, 2012 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -39,6 +39,8 @@
 #include "dnsinfo_private.h"
 #include "dnsinfo_create.h"
 
+static uint32_t _dnsinfo_flatfile_flags;
+
 enum {
        TOKEN_DOMAIN,
        TOKEN_FLAGS,
@@ -233,6 +235,34 @@ _dnsinfo_parse_sortaddr(char *token)
 }
 
 
+/*
+ * _dnsinfo_flatfile_set_flags
+ *
+ * Set the default resolver flags.
+ */
+__private_extern__
+void
+_dnsinfo_flatfile_set_flags(uint32_t flags)
+{
+       _dnsinfo_flatfile_flags = flags;
+       return;
+}
+
+
+static void
+_dnsinfo_flatfile_update_flags(dns_create_resolver_t *_resolver)
+{
+       uint32_t                new_flags;
+       uint32_t                old_flags;
+       _dns_resolver_buf_t     *resolver       = (_dns_resolver_buf_t *)*_resolver;
+
+       old_flags = ntohl(resolver->resolver.flags);
+       new_flags = old_flags | _dnsinfo_flatfile_flags;
+       _dns_resolver_set_flags(_resolver, new_flags);
+       return;
+}
+
+
 /*
  * _dnsinfo_flatfile_create_resolver
  *
@@ -243,6 +273,7 @@ static dns_create_resolver_t
 _dnsinfo_flatfile_create_resolver(const char *dir, const char *path)
 {
        char                    *buf;
+       uint32_t                config_flags            = 0;
        FILE                    *f;
        char                    filename[FILENAME_MAX];
        size_t                  len                     = 0;
@@ -339,20 +370,18 @@ _dnsinfo_flatfile_create_resolver(const char *dir, const char *path)
                        }
 
                        case TOKEN_FLAGS: {
-                               uint32_t        flags   = 0;
-
                                while (word != NULL) {
                                        if (word[0] != '\0') {
                                                if (strcasecmp(word, "scoped") == 0) {
-                                                       flags |= DNS_RESOLVER_FLAGS_SCOPED;
+                                                       config_flags |= DNS_RESOLVER_FLAGS_SCOPED;
+                                               } else if (strcasecmp(word, "a") == 0) {
+                                                       config_flags |= DNS_RESOLVER_FLAGS_REQUEST_A_RECORDS;
+                                               } else if (strcasecmp(word, "aaaa") == 0) {
+                                                       config_flags |= DNS_RESOLVER_FLAGS_REQUEST_AAAA_RECORDS;
                                                }
                                        }
                                        word = strsep(&lineptr, sep);
                                }
-
-                               if (flags != 0) {
-                                       _dns_resolver_set_flags(&res, flags);
-                               }
                                break;
                        }
 
@@ -480,6 +509,15 @@ _dnsinfo_flatfile_create_resolver(const char *dir, const char *path)
                _dns_resolver_set_domain(&res, domain);
        }
 
+       if (res != NULL) {
+               // config flags should overwrite any default flags
+               if (config_flags != 0) {
+                       _dns_resolver_set_flags(&res, config_flags);
+               } else {
+                       _dnsinfo_flatfile_update_flags(&res);
+               }
+       }
+
     done :
 
        fclose(f);
@@ -493,6 +531,7 @@ _dnsinfo_flatfile_create_resolver(const char *dir, const char *path)
  * Parse the files in the resolver config directory (/etc/resolver) and add each
  * resolver to the dns config.
  */
+__private_extern__
 void
 _dnsinfo_flatfile_add_resolvers(dns_create_config_t *config)
 {
diff --git a/dnsinfo/dnsinfo_internal.h b/dnsinfo/dnsinfo_internal.h
new file mode 100644 (file)
index 0000000..a7dc643
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2013 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@
+ */
+
+#ifndef _S_DNSINFO_INTERNAL_H
+#define _S_DNSINFO_INTERNAL_H
+
+#include <Availability.h>
+#include <TargetConditionals.h>
+#include <sys/cdefs.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCPrivate.h>
+#include "SCNetworkReachabilityInternal.h"
+#include <arpa/inet.h>
+
+#include <dnsinfo.h>
+
+__BEGIN_DECLS
+
+static __inline__ void
+_dns_resolver_print(dns_resolver_t *resolver, int index)
+{
+       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);
+       }
+
+       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->service_identifier != 0) {
+               SCPrint(TRUE, stdout, CFSTR("  service_identifier : %d\n"),
+                       resolver->service_identifier);
+       }
+
+       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 & DNS_RESOLVER_FLAGS_SERVICE_SPECIFIC) {
+                       SCPrint(TRUE, stdout, CFSTR("Service-specific"));
+                       flags &= ~DNS_RESOLVER_FLAGS_SERVICE_SPECIFIC;
+                       SCPrint(flags != 0, stdout, CFSTR(", "));
+               }
+               if (flags & DNS_RESOLVER_FLAGS_REQUEST_A_RECORDS) {
+                       SCPrint(TRUE, stdout, CFSTR("Request A records"));
+                       flags &= ~DNS_RESOLVER_FLAGS_REQUEST_A_RECORDS;
+                       SCPrint(flags != 0, stdout, CFSTR(", "));
+               }
+               if (flags & DNS_RESOLVER_FLAGS_REQUEST_AAAA_RECORDS) {
+                       SCPrint(TRUE, stdout, CFSTR("Request AAAA records"));
+                       flags &= ~DNS_RESOLVER_FLAGS_REQUEST_AAAA_RECORDS;
+                       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 (resolver->reach_flags != 0) {
+               uint32_t        flags   = resolver->reach_flags;
+
+               SCPrint(TRUE, stdout, CFSTR("  reach    : "));
+               SCPrint(_sc_debug, stdout, CFSTR("0x%08x ("), flags);
+               __SCNetworkReachabilityPrintFlags(flags);
+               SCPrint(_sc_debug, stdout, CFSTR(")"));
+               SCPrint(TRUE, stdout, CFSTR("\n"));
+       }
+
+       if (resolver->search_order != 0) {
+               SCPrint(TRUE, stdout, CFSTR("  order    : %d\n"), resolver->search_order);
+       }
+
+       return;
+}
+
+
+static __inline__ void
+_dns_configuration_print(dns_config_t *dns_config)
+{
+       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];
+
+               _dns_resolver_print(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"));
+
+               for (i = 0; i < dns_config->n_scoped_resolver; i++) {
+                       dns_resolver_t  *resolver       = dns_config->scoped_resolver[i];
+
+                       _dns_resolver_print(resolver, i + 1);
+               }
+       }
+
+       if ((dns_config->n_service_specific_resolver > 0) && (dns_config->service_specific_resolver != NULL)) {
+               SCPrint(TRUE, stdout, CFSTR("\nDNS configuration (for service-specific queries)\n"));
+
+               for (i = 0; i < dns_config->n_service_specific_resolver; i++) {
+                       dns_resolver_t  *resolver       = dns_config->service_specific_resolver[i];
+
+                       _dns_resolver_print(resolver, i + 1);
+               }
+       }
+
+       return;
+}
+
+__END_DECLS
+
+#endif /* !_S_DNSINFO_INTERNAL_H */
diff --git a/dnsinfo/dnsinfo_private.c b/dnsinfo/dnsinfo_private.c
deleted file mode 100644 (file)
index f7b256f..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2004, 2005, 2007, 2009 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@
- */
-
-/*
- * Modification History
- *
- * March 9, 2004               Allan Nathanson <ajn@apple.com>
- * - initial revision
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <mach/mach.h>
-#include <mach/mach_error.h>
-#include <servers/bootstrap.h>
-#include <bootstrap_priv.h>
-
-#include "dnsinfo_private.h"
-#include "shared_dns_info_types.h"
-
-
-__private_extern__
-const char *
-_dns_configuration_notify_key()
-{
-       return "com.apple.system.SystemConfiguration.dns_configuration";
-}
-
-
-__private_extern__
-mach_port_t
-_dns_configuration_server_port()
-{
-       mach_port_t     server          = MACH_PORT_NULL;
-       char            *server_name;
-       kern_return_t   status;
-
-       server_name = getenv("DNS_SERVER");
-       if (!server_name) {
-               server_name = DNS_SERVER;
-       }
-
-#ifdef BOOTSTRAP_PRIVILEGED_SERVER
-       status = bootstrap_look_up2(bootstrap_port,
-                                   server_name,
-                                   &server,
-                                   0,
-                                   BOOTSTRAP_PRIVILEGED_SERVER);
-#else  // BOOTSTRAP_PRIVILEGED_SERVER
-       status = bootstrap_look_up(bootstrap_port, server_name, &server);
-#endif // BOOTSTRAP_PRIVILEGED_SERVER
-
-       switch (status) {
-               case BOOTSTRAP_SUCCESS :
-                       /* service currently registered, "a good thing" (tm) */
-                       break;
-               case BOOTSTRAP_NOT_PRIVILEGED :
-                       /* the service is not privileged */
-                       return MACH_PORT_NULL;
-               case BOOTSTRAP_UNKNOWN_SERVICE :
-                       /* service not currently registered, try again later */
-                       return MACH_PORT_NULL;
-               default :
-                       fprintf(stderr,
-                               "could not lookup DNS configuration info service: %s\n",
-                               bootstrap_strerror(status));
-                       return MACH_PORT_NULL;
-       }
-
-       return server;
-}
-
index 58128a8e05b745330ef3ac2d13d8ecc2da115015..d6e65b5fcac6c7ba1bb29b7ab2fb849841201cdd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2006, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2006, 2008, 2009, 2012, 2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * | |             | |                   |                             |    resolver configurations  that will
  * | |             | |                   |                             |    be established in the "padding"
  * | |             | +-------------------+-----------------------------+
+ * | |             | | generation        | uint64_t                    | <- generation # of configuration
+ * | |             | +-------------------+---------+-------------------+
+ * | |             | | n_service_specific_resolver | int32_t           | <- # of name service-specific resolvers
+ * | |             | +-------------------+---------+-------------------+
+ * | |             | | service_specific_resolver   | dns_resolver_t ** | <- not used during creation, filled
+ * | |             | |                             |                   |    in with pointer to a list of service-specific
+ * | |             | |                             |                   |    resolver configurations that will be
+ * | |             | |                             |                   |    established in the "padding"
+ * | |             | +-------------------+---------+-------------------+
  * | |             | | ...               | ...                         |
  * | +-------------+-+-------------------+-----------------------------+
  * | | n_attribute | uint32_t                                          | <- how many bytes of "attribute"
 enum {
        CONFIG_ATTRIBUTE_RESOLVER       = 1,
        CONFIG_ATTRIBUTE_SCOPED_RESOLVER,
+       CONFIG_ATTRIBUTE_SERVICE_SPECIFIC_RESOLVER,
 };
 
 
@@ -161,8 +171,6 @@ enum {
        RESOLVER_ATTRIBUTE_ADDRESS,
        RESOLVER_ATTRIBUTE_SEARCH,
        RESOLVER_ATTRIBUTE_SORTADDR,
-       RESOLVER_ATTRIBUTE_IF_INDEX,
-       RESOLVER_ATTRIBUTE_FLAGS,
        RESOLVER_ATTRIBUTE_OPTIONS,
 };
 
@@ -197,19 +205,6 @@ typedef struct {
 
 __BEGIN_DECLS
 
-/*
- * NOTE: __private_extern__ and __OSX_AVAILABLE_STARTING() cannot be mixed
- *       due to a "visibility" conflict
- */
-
-__private_extern__
-const char *
-_dns_configuration_notify_key  ()      /*__OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0)*/;
-
-__private_extern__
-mach_port_t
-_dns_configuration_server_port ()      /*__OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0)*/;
-
 __END_DECLS
 
 #endif /* __DNSINFO_PRIVATE_H__ */
index 1d8bcace732da3a807088d317c497b82b95482da..9a3e588be58e154787023c23621a348ca6123333 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2008, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2008, 2011, 2012 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #include <mach/mach.h>
 #include <mach/mach_error.h>
 #include <bsm/libbsm.h>
+#include <dispatch/dispatch.h>
+#include <xpc/xpc.h>
 
 #include <CoreFoundation/CoreFoundation.h>
 #include <SystemConfiguration/SCPrivate.h>
 
+#include "libSystemConfiguration_client.h"
+#include "libSystemConfiguration_server.h"
+
+#include "dnsinfo_create.h"
 #include "dnsinfo_server.h"
 #include "dnsinfo_private.h"
-#include <network_information.h>
 
-static CFDataRef       shared_dns_info         = NULL;
-static  CFDataRef      shared_nwi_state        = NULL;
+#pragma mark -
+#pragma mark Globals
 
-__private_extern__
-kern_return_t
-_shared_dns_infoGet(mach_port_t server, dnsDataOut_t *dataRef, mach_msg_type_number_t *dataLen)
-{
-       *dataRef = NULL;
-       *dataLen = 0;
 
-       if (shared_dns_info != NULL) {
-               CFIndex len;
-               Boolean ok;
+/*
+ * S_dns_info
+ *
+ * Note: all accesses should be made while running on the _dns_server_queue()
+ */
+static libSC_info_server_t     S_dns_info;
+
 
-               ok = _SCSerializeData(shared_dns_info, (void **)dataRef, &len);
-               *dataLen = len;
-               if (!ok) {
-                       return KERN_FAILURE;
-               }
+/*
+ * S_debug
+ *     A boolean that enables additional logging.
+ */
+static Boolean         *S_debug = NULL;
+static SCLoggerRef     S_logger = NULL;
+
+
+/*
+ * S_sync_handler
+ *     ACK (in-sync or not-in-sync) updates should be posted using
+ *     this handler
+ *
+ * Note: all accesses should be made while running on the _dns_server_queue()
+ */
+static _dns_sync_handler_t     S_sync_handler  = NULL;
+
+
+#pragma mark -
+#pragma mark Support functions
+
+
+#ifdef NOT_YET_NEEDED
+static void
+log_xpc_object(const char *msg, xpc_object_t obj)
+{
+       char            *desc;
+
+       desc = xpc_copy_description(obj);
+       if (*S_debug) {
+               SCLoggerLog(S_logger, LOG_INFO, CFSTR("%s = %s"), msg, desc);
        }
+       free(desc);
+}
+#endif
+
+
+#pragma mark -
+#pragma mark DNS configuration server
 
-       return KERN_SUCCESS;
+
+static dispatch_queue_t
+_dnsinfo_server_queue()
+{
+       static dispatch_once_t  once;
+       static dispatch_queue_t q;
+
+       dispatch_once(&once, ^{
+               q = dispatch_queue_create(DNSINFO_SERVICE_NAME ".server", NULL);
+       });
+
+       return q;
 }
 
 
-static
-kern_return_t
-_shared_infoSet_common(mach_port_t             server,
-                      dnsData_t                dataRef,
-                      mach_msg_type_number_t   dataLen,
-                      audit_token_t            audit_token,
-                      CFDataRef*               cache,
-                      const char*              notify_key)
+/*
+ * _dnsinfo_copy
+ *
+ * Called when a client wants a copy of the current
+ * DNS configuration
+ *
+ * - caller must be running on the _dns_server_queue()
+ */
+static void
+_dnsinfo_copy(xpc_connection_t connection, xpc_object_t request)
 {
-       uid_t           euid            = 0;
-       CFDataRef       new_info        = NULL;
-       CFDataRef       n_cache         = *cache;
+       CFDataRef               data;
+       uint64_t                generation;
+       xpc_connection_t        remote;
+       xpc_object_t            reply;
+
+       remote = xpc_dictionary_get_remote_connection(request);
+       reply = xpc_dictionary_create_reply(request);
+       if (reply == NULL) {
+               SCLoggerLog(S_logger, LOG_ERR,
+                           CFSTR("<%p> _dnsinfo_copy: xpc_dictionary_create_reply: failed"),
+                           connection);
+               return;
+       }
 
-       if ((dataRef != NULL) && (dataLen > 0)) {
-               if (!_SCUnserializeData(&new_info, (void *)dataRef, dataLen)) {
-                       goto error;
+       // extract data and generation #
+       data = _libSC_info_server_get_data(&S_dns_info,
+                                          connection,
+                                          &generation);
+
+       if (*S_debug) {
+               const char      *proc_name;
+
+               // extract process name
+               proc_name = xpc_dictionary_get_string(request, DNSINFO_PROC_NAME);
+               if (proc_name == NULL) {
+                       proc_name = "???";
                }
+
+               SCLoggerLog(S_logger, LOG_INFO, CFSTR("<%p:%s[%d]> DNS configuration copy: %llu"),
+                           connection,
+                           proc_name,
+                           xpc_connection_get_pid(connection),
+                           generation);
        }
 
-       audit_token_to_au32(audit_token,
-                           NULL,       // auidp
-                           &euid,      // euid
-                           NULL,       // egid
-                           NULL,       // ruid
-                           NULL,       // rgid
-                           NULL,       // pid
-                           NULL,       // asid
-                           NULL);      // tid
-       if (euid != 0) {
-               goto error;
+       // return the DNS configuration (if available)
+       if (data != NULL) {
+               xpc_dictionary_set_data(reply,
+                                       DNSINFO_CONFIGURATION,
+                                       CFDataGetBytePtr(data),
+                                       CFDataGetLength(data));
        }
 
-       if ((n_cache != NULL) &&
-           (new_info != NULL) &&
-           CFEqual(n_cache, new_info)) {
-               CFRelease(new_info);
-               return KERN_SUCCESS;
+       // reply
+       xpc_connection_send_message(remote, reply);
+       xpc_release(reply);
+
+       return;
+}
+
+
+/*
+ * _dnsinfo_acknowledge
+ *
+ * Called when a client wants to acknowledge processing
+ * of the DNS configuration
+ *
+ * - caller must be running on the _dns_server_queue()
+ */
+static void
+_dnsinfo_acknowledge(xpc_connection_t connection, xpc_object_t request)
+{
+       uint64_t        generation;
+       Boolean         inSync;
+
+       generation = xpc_dictionary_get_uint64(request, DNSINFO_GENERATION);
+
+       if (*S_debug) {
+               SCLoggerLog(S_logger, LOG_INFO, CFSTR("<%p:%d> DNS configuration ack: %llu"),
+                           connection,
+                           xpc_connection_get_pid(connection),
+                           generation);
        }
 
-       if (n_cache != NULL) CFRelease(n_cache);
-       *cache = new_info;
+       (void) _libSC_info_server_acknowledged(&S_dns_info, connection, generation);
 
-       if (notify_key != NULL) {
-               uint32_t        status;
+       // Note: all of the mDNSResponder ack's should result
+       //       in a [new] network change being posted
 
-               status = notify_post(notify_key);
-               if (status != NOTIFY_STATUS_OK) {
-                       SCLog(TRUE, LOG_ERR, CFSTR("notify_post() failed: %d"), status);
-                       // notification posting failures are non-fatal
-               }
+       inSync = _libSC_info_server_in_sync(&S_dns_info);
+       S_sync_handler(inSync);
+
+       return;
+}
+
+
+static void
+process_request(xpc_connection_t connection, xpc_object_t request)
+{
+       int64_t         op;
+
+       op = xpc_dictionary_get_int64(request, DNSINFO_REQUEST);
+       switch (op) {
+               case DNSINFO_REQUEST_COPY :
+                       /*
+                        * Return the DNS configuration
+                        */
+                       _dnsinfo_copy(connection, request);
+                       break;
+
+               case DNSINFO_REQUEST_ACKNOWLEDGE :
+                       /*
+                        * Acknowlege a [processed] DNS configuration
+                        */
+                       _dnsinfo_acknowledge(connection, request);
+
+                       break;
+               default :
+                       SCLoggerLog(S_logger, LOG_ERR,
+                                   CFSTR("<%p> unknown request : %d"),
+                                   connection,
+                                   op);
+
+                       break;
        }
 
-       return KERN_SUCCESS;
+       return;
+}
 
-    error :
 
-       if (new_info != NULL)    CFRelease(new_info);
-       return KERN_FAILURE;
+static void
+process_new_connection(xpc_connection_t c)
+{
+       if (*S_debug) {
+               SCLoggerLog(S_logger, LOG_INFO, CFSTR("<%p:%d> DNS configuration session: open"),
+                           c,
+                           xpc_connection_get_pid(c));
+       }
+
+       _libSC_info_server_open(&S_dns_info, c);
+
+       xpc_connection_set_target_queue(c, _dnsinfo_server_queue());
+
+       xpc_connection_set_event_handler(c, ^(xpc_object_t xobj) {
+               xpc_type_t      type;
+
+               type = xpc_get_type(xobj);
+               if (type == XPC_TYPE_DICTIONARY) {
+                       // process the request
+                       process_request(c, xobj);
+
+               } 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) {
+                               Boolean         changed;
+
+                               if (*S_debug) {
+                                       SCLoggerLog(S_logger, LOG_INFO, CFSTR("<%p:%d> DNS configuration session: close"),
+                                                   c,
+                                                   xpc_connection_get_pid(c));
+                               }
+
+                               changed = _libSC_info_server_close(&S_dns_info, c);
+                               if (changed) {
+                                       Boolean         inSync;
+
+                                       // report change
+                                       inSync = _libSC_info_server_in_sync(&S_dns_info);
+                                       S_sync_handler(inSync);
+                               }
+
+                       } else if (xobj == XPC_ERROR_CONNECTION_INTERRUPTED) {
+                               SCLoggerLog(S_logger, LOG_ERR,
+                                           CFSTR("<%p:%d> %s"),
+                                           c,
+                                           xpc_connection_get_pid(c),
+                                           desc);
+
+                       } else {
+                               SCLoggerLog(S_logger, LOG_ERR,
+                                           CFSTR("<%p:%d> Connection error: %d : %s"),
+                                           c,
+                                           xpc_connection_get_pid(c),
+                                           xobj,
+                                           desc);
+                       }
+
+               }  else {
+                       SCLoggerLog(S_logger, LOG_ERR,
+                                   CFSTR("<%p:%d> unknown event type : %x"),
+                                   c,
+                                   xpc_connection_get_pid(c),
+                                   type);
+               }
+       });
+
+       xpc_connection_resume(c);
+
+       return;
 }
 
 
+#pragma mark -
+#pragma mark DNS configuration server SPIs
+
+
 __private_extern__
-kern_return_t
-_shared_dns_infoSet(mach_port_t                        server,
-                   dnsData_t                   dataRef,
-                   mach_msg_type_number_t      dataLen,
-                   audit_token_t               audit_token)
+void
+load_DNSConfiguration(CFBundleRef              bundle,
+                     SCLoggerRef               logger,
+                     Boolean                   *bundleVerbose,
+                     _dns_sync_handler_t       syncHandler)
 {
-       const char      *notify_key;
+       xpc_connection_t        c;
+       const char              *name;
+
+       S_debug = bundleVerbose;
+       S_logger = logger;
+
+       /*
+        * keep track of DNS configuration acknowledgements
+        */
+       _libSC_info_server_init(&S_dns_info);
+
+       /*
+        * save the in-sync/not-in-sync handler
+        */
+       S_sync_handler = Block_copy(syncHandler);
+
+       // create XPC listener
+       name = getenv(DNSINFO_SERVICE_NAME);
+       if (name == NULL) {
+               name = DNSINFO_SERVICE_NAME;
+       }
+
+       c = xpc_connection_create_mach_service(name,
+                                              _dnsinfo_server_queue(),
+                                              XPC_CONNECTION_MACH_SERVICE_LISTENER);
+
+       xpc_connection_set_event_handler(c, ^(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) {
+                               SCLoggerLog(S_logger, LOG_ERR, CFSTR("DNS configuration server: %s"), desc);
+                               xpc_release(c);
+                       } else if (event == XPC_ERROR_CONNECTION_INTERRUPTED) {
+                               SCLoggerLog(S_logger, LOG_ERR, CFSTR("DNS configuration server: %s"), desc);
+                       } else {
+                               SCLoggerLog(S_logger, LOG_ERR,
+                                     CFSTR("DNS configuration server: Connection error: %d : %s"),
+                                     event,
+                                     desc);
+                       }
+
+               } else {
+                       SCLoggerLog(S_logger, LOG_ERR,
+                                   CFSTR("DNS configuration server: unknown event type : %x"),
+                                   type);
+
+               }
+       });
+
+       xpc_connection_resume(c);
+
+SCLoggerLog(S_logger, LOG_DEBUG, CFSTR("XPC server \"%s\" started"), name);
 
-       notify_key = _dns_configuration_notify_key();
-       return _shared_infoSet_common(server, dataRef, dataLen,
-                                     audit_token, &shared_dns_info,
-                                     notify_key);
+       return;
 }
 
 
 __private_extern__
-kern_return_t
-_shared_nwi_stateGet(mach_port_t server, dnsDataOut_t *dataRef, mach_msg_type_number_t *dataLen)
+_Bool
+_dns_configuration_store(dns_create_config_t *_config)
 {
-       *dataRef = NULL;
-       *dataLen = 0;
+       _dns_config_buf_t       *config         = (_dns_config_buf_t *)*_config;
+       Boolean                 in_sync;
+       uint64_t                new_generation  = 0;
+       CFDataRef               new_dns_info    = NULL;
+       const char              *notify_key;
 
-       if (shared_nwi_state != NULL) {
-               CFIndex len;
-               Boolean ok;
+       if (config != NULL) {
+               const UInt8     *bytes;
+               CFIndex         len;
 
-               ok = _SCSerializeData(shared_nwi_state, (void **)dataRef, &len);
-               *dataLen = len;
-               if (!ok) {
-                       return KERN_FAILURE;
+               new_generation = config->config.generation;
+
+               if (*S_debug) {
+                       SCLoggerLog(S_logger, LOG_INFO, CFSTR("DNS configuration updated: %llu"),
+                                   new_generation);
                }
+
+               bytes = (const UInt8 *)config;
+               len = sizeof(_dns_config_buf_t) + ntohl(config->n_attribute);
+
+               new_dns_info = CFDataCreate(NULL, bytes, len);
        }
 
-       return KERN_SUCCESS;
+       dispatch_sync(_dnsinfo_server_queue(), ^{
+               _libSC_info_server_set_data(&S_dns_info, new_dns_info, new_generation);
+       });
+
+       if (new_dns_info != NULL) {
+               CFRelease(new_dns_info);
+       }
+
+       // if anyone is keeping us in sync, they now need to catch up
+       in_sync = _libSC_info_server_in_sync(&S_dns_info);
+       S_sync_handler(in_sync);
+
+       // and let everyone else know that the configuration has been updated
+       notify_key = dns_configuration_notify_key();
+       if (notify_key != NULL) {
+               uint32_t        status;
 
+               status = notify_post(notify_key);
+               if (status != NOTIFY_STATUS_OK) {
+                       SCLoggerLog(S_logger, LOG_ERR, CFSTR("notify_post() failed: %d"), status);
+                       // notification posting failures are non-fatal
+               }
+       }
+
+       return TRUE;
 }
 
 
-__private_extern__
-kern_return_t
-_shared_nwi_stateSet(mach_port_t               server,
-                    dnsData_t                  dataRef,
-                    mach_msg_type_number_t     dataLen,
-                    audit_token_t              audit_token)
-{
-       const char      *notify_key;
+#pragma mark -
+#pragma mark Testing
+
 
-       notify_key = nwi_state_get_notify_key();
+#ifdef  MAIN
 
-       return _shared_infoSet_common(server, dataRef, dataLen,
-                                     audit_token, &shared_nwi_state,
-                                     notify_key);
+int
+main(int argc, char **argv)
+{
+       static Boolean verbose = (argc > 1) ? TRUE : FALSE;
+//     _sc_log     = FALSE;
+       _sc_verbose = (argc > 1) ? TRUE : FALSE;
+       _sc_debug   = TRUE;
+
+       load_DNSConfiguration(CFBundleGetMainBundle(),          // bundle
+                             NULL,                             //SCLogger
+                             &verbose,                         // bundleVerbose
+                             ^(Boolean inSync) {               // sync handler
+                                     SCLoggerLog(NULL, LOG_INFO,
+                                           CFSTR("in sync: %s"),
+                                           inSync ? "Yes" : "No")
+                             });
+       CFRunLoopRun();
+       /* not reached */
+       exit(0);
+       return 0;
 }
+
+#endif  /* MAIN */
index 7483a3e41657934a71fd59b4cd2e8f275e0dce18..53b7779d4d043c53b8f3399595147d4e6a7c074f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2005, 2009, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2004, 2005, 2009, 2011, 2012 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #define _S_DNSINFO_SERVER_H
 
 #include <sys/cdefs.h>
+#include <stdbool.h>
 #include <mach/mach.h>
 #include <CoreFoundation/CoreFoundation.h>
+#include <dispatch/dispatch.h>
 
-#include "shared_dns_info_types.h"
+#include "dnsinfo_create.h"
+
+typedef void (^_dns_sync_handler_t)(Boolean inSync);
 
 __BEGIN_DECLS
 
-__private_extern__
-kern_return_t  _shared_dns_infoGet     (mach_port_t            server,
-                                        dnsDataOut_t           *dataRef,
-                                        mach_msg_type_number_t *dataLen);
-
-__private_extern__
-kern_return_t  _shared_dns_infoSet     (mach_port_t            server,
-                                        dnsData_t              dataRef,
-                                        mach_msg_type_number_t dataLen,
-                                        audit_token_t          audit_token);
-
-__private_extern__
-kern_return_t  _shared_nwi_stateGet    (mach_port_t            server,
-                                        dnsDataOut_t           *dataRef,
-                                        mach_msg_type_number_t *dataLen);
-
-__private_extern__
-kern_return_t  _shared_nwi_stateSet    (mach_port_t            server,
-                                        dnsData_t              dataRef,
-                                        mach_msg_type_number_t dataLen,
-                                        audit_token_t          audit_token);
+void
+load_DNSConfiguration                  (CFBundleRef            bundle,
+                                        SCLoggerRef            logger,
+                                        Boolean                *bundleVerbose,
+                                        _dns_sync_handler_t    syncHandler);
+
+_Bool
+_dns_configuration_store               (dns_create_config_t    *_config);
 
 __END_DECLS
 
diff --git a/dnsinfo/shared_dns_info.defs b/dnsinfo/shared_dns_info.defs
deleted file mode 100644 (file)
index 4a24c43..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2004, 2005, 2009, 2011 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@
- */
-
-/*
- * Modification History
- *
- * February 9, 2004            Allan Nathanson <ajn@apple.com>
- * - initial revision
- */
-
-#include <mach/std_types.defs>
-#include <mach/mach_types.defs>
-
-subsystem shared_dns_info 21000;
-serverprefix _;
-
-import "shared_dns_info_types.h";
-
-/*
- * DNS configuration (client->server)
- */
-type dnsData    = ^ array [] of MACH_MSG_TYPE_BYTE
-       ctype : dnsData_t;
-
-/*
- * DNS configuration (server->client)
- */
-type dnsDataOut = ^ array [] of MACH_MSG_TYPE_BYTE
-       ctype : dnsDataOut_t;
-
-/*
- * DNS configuration API's
- */
-
-routine shared_dns_infoGet     (       server          : mach_port_t;
-                                out    data            : dnsDataOut, dealloc);
-
-#ifndef        LIBDNSINFO_A
-routine shared_dns_infoSet     (       server          : mach_port_t;
-                                       data            : dnsData;
-                   ServerAuditToken    audit_token     : audit_token_t);
-#else  // LIBDNSINFO_A
-       skip;           /* shared_dns_infoSet */
-#endif // LIBDNSINFO_A
-
-routine shared_nwi_stateGet     (      server          : mach_port_t;
-                               out     data            : dnsDataOut, dealloc);
-
-#ifndef LIBDNSINFO_A
-routine shared_nwi_stateSet    (       server          : mach_port_t;
-                               data                    : dnsData;
-                   ServerAuditToken    audit_token     : audit_token_t);
-#else   // LIBDNSINFO_A
-       skip;           /* shared_nwi_stateSet */
-#endif  // LIBDNSINFO_A
-
diff --git a/dnsinfo/shared_dns_info_types.h b/dnsinfo/shared_dns_info_types.h
deleted file mode 100644 (file)
index 780cf77..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2004, 2007 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@
- */
-
-#ifndef _SHARED_DNS_INFO_TYPES_H
-#define _SHARED_DNS_INFO_TYPES_H
-
-/*
- * Keep IPC functions private to the framework
- */
-#ifdef mig_external
-#undef mig_external
-#endif
-#define mig_external __private_extern__
-
-/* Turn MIG type checking on by default */
-#ifdef __MigTypeCheck
-#undef __MigTypeCheck
-#endif
-#define __MigTypeCheck 1
-
-/*
- * Mach server port name
- */
-#define DNS_SERVER     "com.apple.SystemConfiguration.configd"
-
-/*
- * Input arguments: DNS configuration
- *     (sent as out-of-line data in a message)
- */
-typedef const char * dnsData_t;
-
-/* Output arguments: DNS configuration
- *     (sent as out-of-line data in a message)
- */
-typedef char * dnsDataOut_t;
-
-#endif /* !_SHARED_DNS_INFO_TYPES_H */
index 818391c119f8fe8aa7f837dfce5f8b9740ee8233..a0b66a9950cabd90ee15ac8fba2b823e43841a95 100755 (executable)
@@ -1,5 +1,5 @@
 #!/bin/sh
-# Copyright (c) 2004-2012 Apple Inc.
+# Copyright (c) 2004-2013 Apple Inc.
 #
 # get-mobility-info
 #
@@ -13,12 +13,20 @@ if [ ${EUID} -ne 0 ]; then
        PRIV="sudo"
 fi
 
+if [ -x /usr/bin/tail ]; then
+       TAIL_2000="/usr/bin/tail -n 2000"
+       TAIL_25000="/usr/bin/tail -n 25000"
+else
+       TAIL_2000="/bin/cat"
+       TAIL_25000="/bin/cat"
+fi
+
 OUT="mobility-info-`date +'%m.%d.%Y.%H%M%S'`"
 OUTDIR="/var/tmp"
 if [ -d ~/Desktop ]; then
        OUTDIR=~/Desktop
 elif [ "`readlink /tmp`" = "private/var/tmp" ]; then
-       OUTDIR=/Library/Logs/CrashReporter/SystemConfiguration
+       OUTDIR=/Library/Logs/CrashReporter
        mkdir -p ${OUTDIR}
 fi
 
@@ -50,35 +58,63 @@ echo ""
 echo "Please wait, collecting information and statistics"
 echo ""
 
+#
+# Execute network reachability/DNS commands early as "mDNSResponder" will block while
+# logging its "state" info.
+#
+scutil -d -v -r www.apple.com "" no-server             > reachability-info     2>&1
+if [ -x /usr/bin/dig -a -f /etc/resolv.conf ]; then
+       /usr/bin/dig -t any -c any www.apple.com        > dig-results           2>/dev/null
+fi
+
+#
+# Signal "networkd" and "mDNSResponder" to log their "state" info. This logging will
+# continue while we execute a few other commands and should be complete by the time
+# we collect the log content.
+#
+if [ -x /usr/bin/killall ]; then
+       ${PRIV} /usr/bin/killall -INFO networkd
+       ${PRIV} /usr/bin/killall -INFO mDNSResponder
+       sleep 1
+fi
+
 #
 # processes
 #
-ps axlww                                               > ps                    2>&1
+if [ -x /bin/ps ]; then
+       /bin/ps axlww                                   > ps                    2>&1
+fi
 
 #
 # network interface configuration
 #
-ifconfig -a -L -b -m -r -v                             > ifconfig              2>&1
-if [ $? -ne 0 ]; then
-       ifconfig -a                                     > ifconfig              2>&1
+if [ -x /sbin/ifconfig ]; then
+       /sbin/ifconfig -a -L -b -m -r -v -v             > ifconfig              2>&1
+       if [ $? -ne 0 ]; then
+               /sbin/ifconfig -a                       > ifconfig              2>&1
+       fi
 fi
 
 #
 # network route configuration
 #
-netstat -n -r -a -l                                    > netstat               2>&1
+if [ -x /usr/sbin/netstat ]; then
+       /usr/sbin/netstat -n -r -a -l                   > netstat               2>&1
+fi
 
 #
 # DHCP configuration
 #
-for if in `ifconfig -l`
-do
-       case ${if} in
-       lo* )   ;;
-       en* )   ipconfig getpacket ${if}                > ipconfig-${if}        2>&1
-               ;;
-       esac
-done
+if [ -x /sbin/ifconfig ]; then
+       for if in `/sbin/ifconfig -l`
+       do
+               case ${if} in
+               lo* )   ;;
+               en* )   ipconfig getpacket ${if}        > ipconfig-${if}        2>&1
+                       ;;
+               esac
+       done
+fi
 
 #
 # AirPort info
@@ -88,6 +124,22 @@ if [ -x /System/Library/PrivateFrameworks/Apple80211.framework/Resources/airport
                                                        > airport               2>&1
 fi
 
+#
+# collect wifi dump
+#
+if [ -x /usr/bin/wdutil ]; then
+       ${PRIV} /usr/bin/wdutil dump
+       mkdir -p "wifi_dump"
+       /bin/ls -1 /private/tmp/wifi-*                                          2>/dev/null     \
+       | while read log
+       do
+               if [ -f "${log}" ]; then
+                       b="`basename ${log}`"
+                       ${PRIV} cat "${log}"            > "wifi_dump/${b}"      2>&1
+               fi
+       done
+fi
+
 #
 # OS info
 #
@@ -103,41 +155,34 @@ fi
 #
 # IOKit info
 #
-ioreg -i -l -w 0                                       >  ioreg                2>&1
-ioreg -i -l -p IODeviceTree -w 0                       >> ioreg                2>&1
+if [ -x /usr/sbin/ioreg ]; then
+       /usr/sbin/ioreg -i -l -w 0                      >  ioreg                2>&1
+       /usr/sbin/ioreg -i -l -p IODeviceTree -w 0      >> ioreg                2>&1
+fi
 
 #
 # Power Management info
 #
-echo "#"                                               >  pmset
-echo "# pmset -g"                                      >> pmset
-echo "#"                                               >> pmset
-pmset -g                                               >> pmset                2>&1
-
-echo "#"                                               >> pmset
-echo "# pmset -g ps"                                   >> pmset
-echo "#"                                               >> pmset
-pmset -g ps                                            >> pmset                2>&1
-
-echo "#"                                               >> pmset
-echo "# pmset -g assertions"                           >> pmset
-echo "#"                                               >> pmset
-pmset -g assertions                                    >> pmset                2>&1
-
-echo "#"                                               >> pmset
-echo "# pmset -g log"                                  >> pmset
-echo "#"                                               >> pmset
-pmset -g log  | tail -n 25000                          >> pmset                2>&1
+if [ -x /usr/bin/pmset ]; then
+       echo "#"                                                        >  pmset
+       echo "# pmset -g everything"                                    >> pmset
+       echo "#"                                                        >> pmset
+       /usr/bin/pmset -g everything 2>/dev/null  | ${TAIL_25000}       >> pmset
+fi
 
 #
 # Host name
 #
-hostname                                               > hostname              2>&1
+if [ -x /bin/hostname ]; then
+       /bin/hostname                                   > hostname              2>&1
+fi
 
 #
 # Host configuration
 #
-hostinfo                                               > hostinfo              2>&1
+if [ -x /usr/bin/hostinfo ]; then
+       /usr/bin/hostinfo                               > hostinfo              2>&1
+fi
 if [ -e /etc/hostconfig ]; then
        cat /etc/hostconfig                             > etc.hostconfig        2>&1
 fi
@@ -152,6 +197,9 @@ fi
 if [ -e /var/run/resolv.conf ]; then
        cat /var/run/resolv.conf                        > var.run.resolv.conf   2>&1
 fi
+if [ -e /etc/resolver ]; then
+       tar -c -H /etc/resolver                         > etc.resolver.tar      2>/dev/null
+fi
 
 #
 # Proxy configuration
@@ -161,7 +209,20 @@ scutil -d -v --proxy                                       > proxy-configuration   2>&1
 #
 # Network information
 #
-scutil --nwi                                           > network-information   2>&1
+if [ -x /sbin/ifconfig ]; then
+       echo "#"                                        >  network-information
+       echo "# scutil --nwi"                           >> network-information
+       echo "#"                                        >> network-information
+       scutil --nwi                                    >> network-information  2>&1
+       for if in `/sbin/ifconfig -l`
+       do
+               echo ""                                 >> network-information
+               echo "#"                                >> network-information
+               echo "# scutil --nwi ${if}"             >> network-information
+               echo "#"                                >> network-information
+               scutil --nwi ${if}                      >> network-information  2>&1
+       done
+fi
 
 #
 # System / network preferences
@@ -185,6 +246,27 @@ do
        fi
 done
 
+#
+# System / network preferences (from other volumes)
+#
+mount                                                                                  \
+| awk 'BEGIN { FS= "[/ \t]+" } /^\/dev\/disk.* on \/Volumes\// { print $6 }'           \
+| while read volume
+do
+       V_PATH="/Volumes/${volume}"
+       for f in                                                                        \
+               /Library/Preferences/SystemConfiguration/Networkinterfaces.plist        \
+               /Library/Preferences/SystemConfiguration/preferences.plist              \
+
+       do
+               if [ -f "${V_PATH}/${f}" ]; then
+                       mkdir -p "OtherPreferences/${volume}"
+                       b="`basename ${f}`"
+                       cat "${V_PATH}/${f}"            > "OtherPreferences/${volume}/${b}"     2>&1
+               fi
+       done
+done
+
 #
 # InternetSharing
 #
@@ -216,211 +298,154 @@ if [ -f /var/tmp/configd-reachability ]; then
        cat /var/tmp/configd-reachability               > configd-reachability          2>&1
 fi
 
-#
-# network reachability
-#
-scutil -d -v -r www.apple.com "" no-server             > reachability-info     2>&1
-if [ -x /usr/bin/dig -a -f /etc/resolv.conf ]; then
-       /usr/bin/dig -t any -c any www.apple.com        > dig-results           2>/dev/null
-fi
-
 #
 # mounted filesystems
 #
 mount                                                  > mounted-filesystems   2>&1
 
-#
-# mDNSResponder, networkd info
-#
-if [ -x /usr/bin/killall ]; then
-       ${PRIV} killall -INFO mDNSResponder
-       ${PRIV} killall -INFO networkd
-
-       # and wait a short amount of time for mDNSResponder
-       # to actually log the requested information
-       sleep 15
-fi
-
-#
-# awacsd info
-#
-if [ -x /usr/sbin/awacsd -a -x /usr/bin/killall ]; then
-       ${PRIV} killall -INFO awacsd                                    2>/dev/null
-
-       # and wait a short amount of time for awacsd
-       # to actually log the requested information
-       sleep 1
-fi
-
-#
-# system log, kernel.log, early boot log messages
-#
-if [ -x /usr/bin/syslog ]; then
-       # save the recent activity
-       ${PRIV} syslog | tail -n 25000                                  > syslog
-
-       # save just the "kernel" activity (in case some of the
-       # interesting/relevant message are before the messages
-       # captured above.
-       ${PRIV} syslog -k Facility kern | tail -n 25000                 > kernel
-
-       if [ -d /var/log/DiagnosticMessages ]; then
-               # save any MessageTracer activity
-               ${PRIV} syslog  -d /var/log/DiagnosticMessages  \
-                               -F raw                          \
-                               -T local                        \
-                       | tail -n 25000                                 > DiagnosticMessages
-       fi
-else
-       if [ -f /var/log/system.log ]; then
-               ${PRIV} tail -n 25000 /var/log/system.log               > system.log
-       fi
-       if [ -f /var/log/kernel.log ]; then
-               ${PRIV} tail -n 25000 /var/log/kernel.log               > kernel.log
-       fi
-fi
-${PRIV} dmesg                                                          > dmesg
-
-#
-# IPConfiguration log
-#
-if [ -f /var/log/com.apple.IPConfiguration.bootp ]; then
-       ${PRIV} tail -n 2000 /var/log/com.apple.IPConfiguration.bootp   \
-                                                       > com.apple.IPConfiguration.bootp
-fi
-
-#
-# ppp log file(s)
-#
-scutil <<_END_OF_INPUT                         \
-| awk -F' *: *'                                        \
-    '                                          \
-     /Logfile : / {                            \
-       if (index($2, "/") == 1) { print $2 }   \
-       else { print "/var/log/ppp/" $2 }       \
-     }                                         \
-     END {                                     \
-       print "/tmp/pppotcp.log"                        \
-     }                                         \
-    '                                          \
-| sort -u                                      \
-| while read logFile
-open
-show Setup:/Network/Service/[^/]+/PPP pattern
-quit
-_END_OF_INPUT
-do
-       if [ -f "${logFile}" ]; then
-               b="`basename ${logFile}`"
-               cat "${logFile}"                        > "${b}"                2>&1
-       fi
-done
-
-#
-# application firewall log
-#
-if [ -f /var/log/appfirewall.log ]; then
-       ${PRIV} tail -n 2000 /var/log/appfirewall.log   > appfirewall.log
-fi
+${PRIV} cat /etc/hosts                                         > etc.hosts             2>/dev/null
 
 #
 # kernel extensions statistic
 #
 if   [ -x /usr/sbin/kextstat ]; then
-       kextstat                                        > kextstat              2>&1
+       /usr/sbin/kextstat                              > kextstat              2>&1
 elif [ -x /usr/sbin/kmodstat ]; then
-       kmodstat                                        > kmodstat              2>&1
+       /usr/sbin/kmodstat                              > kmodstat              2>&1
 fi
 
 #
 # network statistics
 #
-echo "#"                                               >  network-statistics
-echo "# arp -n -a"                                     >> network-statistics
-echo "#"                                               >> network-statistics
-arp -n -a                                              >> network-statistics   2>&1
-
-echo "#"                                               >> network-statistics
-echo "# netstat -n -a -A"                              >> network-statistics
-echo "#"                                               >> network-statistics
-netstat -n -a -A                                       >> network-statistics   2>&1
-
-echo "#"                                               >> network-statistics
-echo "# netstat -s"                                    >> network-statistics
-echo "#"                                               >> network-statistics
-netstat -s                                             >> network-statistics   2>&1
-
-echo "#"                                               >> network-statistics
-echo "# netstat -mmm"                                  >> network-statistics
-echo "#"                                               >> network-statistics
-netstat -mmm                                           >> network-statistics   2>&1
-
-echo "#"                                               >> network-statistics
-echo "# netstat -i -n -d"                              >> network-statistics
-echo "#"                                               >> network-statistics
-netstat -i -n -d                                       >> network-statistics   2>&1
-
-echo "#"                                               >> network-statistics
-echo "# netstat -g -n -s"                              >> network-statistics
-echo "#"                                               >> network-statistics
-netstat -g -n -s                                       >> network-statistics   2>&1
+echo -n ""                                                     >  network-statistics
+
+if   [ -x /usr/sbin/arp ]; then
+       echo "#"                                                >> network-statistics
+       echo "# arp -n -a"                                      >> network-statistics
+       echo "#"                                                >> network-statistics
+       /usr/sbin/arp -n -a                                     >> network-statistics   2>&1
+fi
+
+if [ -x /usr/sbin/netstat ]; then
+       echo "#"                                                >> network-statistics
+       echo "# netstat -n -a -A"                               >> network-statistics
+       echo "#"                                                >> network-statistics
+       /usr/sbin/netstat -n -a -A                              >> network-statistics   2>&1
+
+       echo "#"                                                >> network-statistics
+       echo "# netstat -s"                                     >> network-statistics
+       echo "#"                                                >> network-statistics
+       /usr/sbin/netstat -s                                    >> network-statistics   2>&1
+
+       echo "#"                                                >> network-statistics
+       echo "# netstat -mmm"                                   >> network-statistics
+       echo "#"                                                >> network-statistics
+       /usr/sbin/netstat -mmm                                  >> network-statistics   2>&1
+
+       echo "#"                                                >> network-statistics
+       echo "# netstat -i -n -d"                               >> network-statistics
+       echo "#"                                                >> network-statistics
+       /usr/sbin/netstat -i -n -d                              >> network-statistics   2>&1
+
+       echo "#"                                                >> network-statistics
+       echo "# netstat -g -n -s"                               >> network-statistics
+       echo "#"                                                >> network-statistics
+       /usr/sbin/netstat -g -n -s                              >> network-statistics   2>&1
+
+       echo "#"                                                >> network-statistics
+       echo "# netstat -i -x R"                                >> network-statistics
+       echo "#"                                                >> network-statistics
+       /usr/sbin/netstat -i -x R                               >> network-statistics   2>&1
+       echo "#"                                                >> network-statistics
+
+       echo "# netstat -a -n -p mptcp"                         >> network-statistics
+       echo "#"                                                >> network-statistics
+       /usr/sbin/netstat -a -n -p mptcp                        >> network-statistics   2>/dev/null
+
+       echo "#"                                                >> network-statistics
+       echo "# netstat -s -p mptcp"                            >> network-statistics
+       echo "#"                                                >> network-statistics
+       /usr/sbin/netstat -s -p mptcp                           >> network-statistics   2>/dev/null
+
+       if [ -x /sbin/ifconfig ]; then
+               for if in `/sbin/ifconfig -l`
+               do
+                       `/sbin/ifconfig -v ${if} | grep -q TXSTART`
+                       if [ $? -eq 0 ]; then
+                               echo "#"                        >> network-statistics
+                               echo "# netstat -qq -I ${if}"   >> network-statistics
+                               echo "#"                        >> network-statistics
+                               /usr/sbin/netstat -qq -I ${if}  >> network-statistics   2>&1
+                       fi
+                       `/sbin/ifconfig -v ${if} | grep -q RXPOLL`
+                       if [ $? -eq 0 ]; then
+                               echo "#"                        >> network-statistics
+                               echo "# netstat -Q -I ${if}"    >> network-statistics
+                               echo "#"                        >> network-statistics
+                               /usr/sbin/netstat -Q -I ${if}   >> network-statistics   2>&1
+                       fi
+               done
+       fi
+fi
 
 if [ -x /usr/sbin/ndp ]; then
        echo "#"                                        >> network-statistics
        echo "# ndp -n -a"                              >> network-statistics
        echo "#"                                        >> network-statistics
-       ndp -n -a                                       >> network-statistics   2>&1
+       /usr/sbin/ndp -n -a                             >> network-statistics   2>&1
 
        echo "#"                                        >> network-statistics
        echo "# ndp -n -p"                              >> network-statistics
        echo "#"                                        >> network-statistics
-       ndp -n -p                                       >> network-statistics   2>&1
+       /usr/sbin/ndp -n -p                             >> network-statistics   2>&1
 
        echo "#"                                        >> network-statistics
        echo "# ndp -n -r"                              >> network-statistics
        echo "#"                                        >> network-statistics
-       ndp -n -r                                       >> network-statistics   2>&1
+       /usr/sbin/ndp -n -r                             >> network-statistics   2>&1
 
-       for if in `ifconfig -l`
-       do
-               echo "#"                                >> network-statistics
-               echo "# ndp -i ${if}"                   >> network-statistics
-               echo "#"                                >> network-statistics
-               ndp -i ${if}                            >> network-statistics   2>&1
-       done
+       if [ -x /sbin/ifconfig ]; then
+               for if in `/sbin/ifconfig -l`
+               do
+                       echo "#"                        >> network-statistics
+                       echo "# ndp -i ${if}"           >> network-statistics
+                       echo "#"                        >> network-statistics
+                       /usr/sbin/ndp -i ${if}          >> network-statistics   2>&1
+               done
+       fi
 fi
 
 if [ -x /sbin/ipfw ]; then
        echo "#"                                        >> network-statistics
        echo "# ipfw -at show"                          >> network-statistics
        echo "#"                                        >> network-statistics
-       ${PRIV} ipfw -at show                           >> network-statistics   2>&1
+       ${PRIV} /sbin/ipfw -at show                     >> network-statistics   2>&1
 fi
 
 if [ -x /sbin/ip6fw ]; then
        echo "#"                                        >> network-statistics
-       echo "# ip6fw -at show"                 >> network-statistics
+       echo "# ip6fw -at show"                         >> network-statistics
        echo "#"                                        >> network-statistics
-       ${PRIV} ip6fw -at show                          >> network-statistics   2>&1
+       ${PRIV} /sbin/ip6fw -at show                    >> network-statistics   2>&1
 fi
 
 if [ -x /sbin/pfctl ]; then
        echo "#"                                        >  pf
        echo "# pfctl -s all"                           >> pf
        echo "#"                                        >> pf
-       ${PRIV} pfctl -s all                            >> pf                   2>&1
+       ${PRIV} /sbin/pfctl -s all                      >> pf                   2>&1
        echo "=============================="           >> pf
        echo "#"                                        >> pf
        echo "# pfctl -s References"                    >> pf
        echo "#"                                        >> pf
-       ${PRIV} pfctl -s References                     >> pf                   2>&1
+       ${PRIV} /sbin/pfctl -s References               >> pf                   2>&1
        for ANCHOR in `${PRIV} pfctl -s Anchors -v 2>/dev/null`
        do
                echo "=============================="   >> pf
                echo "#"                                >> pf
                echo "# pfctl -a ${ANCHOR} -s all"      >> pf
                echo "#"                                >> pf
-               ${PRIV} pfctl -a ${ANCHOR} -s all       >> pf                   2>&1
+               ${PRIV} /sbin/pfctl -a ${ANCHOR} -s all >> pf                   2>&1
        done
 fi
 
@@ -428,7 +453,7 @@ if [ -x /usr/sbin/lsof ]; then
        echo "#"                                        >> network-statistics
        echo "# lsof -i -U -n -P"                       >> network-statistics
        echo "#"                                        >> network-statistics
-       ${PRIV} lsof -i -U -n -P                        >> network-statistics   2>&1
+       ${PRIV} /usr/sbin/lsof -i -U -n -P              >> network-statistics   2>&1
 fi
 
 #
@@ -438,425 +463,390 @@ if [ -x /usr/bin/odutil ]; then
        echo "#"                                        >  od-info
        echo "# odutil show all"                        >> od-info
        echo "#"                                        >> od-info
-       ${PRIV} odutil show all                         >> od-info              2>&1
+       ${PRIV} /usr/bin/odutil show all                >> od-info              2>&1
 elif [ -x /usr/bin/dscacheutil ]; then
        echo "#"                                        >  ds-info
        echo "# dscacheutil -configuration"             >> ds-info
        echo "#"                                        >> ds-info
-       dscacheutil -configuration                      >> ds-info              2>&1
+       /usr/bin/dscacheutil -configuration             >> ds-info              2>&1
 
        echo "#"                                        >> ds-info
        echo "# dscacheutil -statistics"                >> ds-info
        echo "#"                                        >> ds-info
-       dscacheutil -statistics                         >> ds-info              2>&1
+       /usr/bin/dscacheutil -statistics                >> ds-info              2>&1
 
        echo "#"                                        >> ds-info
        echo "# dscacheutil -cachedump -entries"        >> ds-info
        echo "#"                                        >> ds-info
-       dscacheutil -cachedump -entries                 >> ds-info              2>&1
+       /usr/bin/dscacheutil -cachedump -entries        >> ds-info              2>&1
 fi
 
 #
 # IPsec configuration
 #
-echo "#"                                               >  ipsec
-echo "# setkey -D"                                     >> ipsec
-echo "#"                                               >> ipsec
-${PRIV} setkey -D                                      \
-| perl -M'Digest::MD5 qw(md5_hex)' -l -n -e '
-       if (/^(\s+[AE]:\s+\S+\s+)"?(.*)"?\s*$/) {
-               printf "%s[MD5:%s]%s\n", $1, md5_hex($2 . "\n"), $3;
-       } else {
-               printf "%s\n", $_;
-       }
-'                                                      >> ipsec
-
-echo ""                                                        >> ipsec
-echo "#"                                               >> ipsec
-echo "# setkey -Pp -D"                                 >> ipsec
-echo "#"                                               >> ipsec
-${PRIV} setkey -Pp -D                                  >> ipsec
-
-for CF in /var/run/racoon/*.conf
-do
-       if [ ! -r "${CF}" ]; then
-               continue
-       fi
-
-       echo ""                                         >> ipsec
-       echo "#"                                        >> ipsec
-       echo "# ${CF}"                                  >> ipsec
-       echo "#"                                        >> ipsec
-       ${PRIV} cat ${CF}                               \
-       | perl -M'Digest::MD5 qw(md5_hex)' -l -n -e '
-               if (/^(\s+shared_secret\s+use\s+)"?([^\s;"]+)"?(.*)/) {
+if [ -x /usr/sbin/setkey -a -x /usr/bin/perl ]; then
+       echo "#"                                                >  ipsec
+       echo "# setkey -D"                                      >> ipsec
+       echo "#"                                                >> ipsec
+       ${PRIV} /usr/sbin/setkey -D                             \
+       | /usr/bin/perl -M'Digest::MD5 qw(md5_hex)' -l -n -e '
+               if (/^(\s+[AE]:\s+\S+\s+)"?(.*)"?\s*$/) {
                        printf "%s[MD5:%s]%s\n", $1, md5_hex($2 . "\n"), $3;
                } else {
                        printf "%s\n", $_;
                }
-       '                                               >> ipsec
-done
+       '                                                       >> ipsec
+
+       echo ""                                                 >> ipsec
+       echo "#"                                                >> ipsec
+       echo "# setkey -Pp -D"                                  >> ipsec
+       echo "#"                                                >> ipsec
+       ${PRIV} /usr/sbin/setkey -Pp -D                         >> ipsec
+
+       for CF in /var/run/racoon/*.conf
+       do
+               if [ ! -r "${CF}" ]; then
+                       continue
+               fi
+
+               echo ""                                         >> ipsec
+               echo "#"                                        >> ipsec
+               echo "# ${CF}"                                  >> ipsec
+               echo "#"                                        >> ipsec
+               ${PRIV} cat ${CF}                               \
+               | /usr/bin/perl -M'Digest::MD5 qw(md5_hex)' -l -n -e '
+                       if (/^(\s+shared_secret\s+use\s+)"?([^\s;"]+)"?(.*)/) {
+                               printf "%s[MD5:%s]%s\n", $1, md5_hex($2 . "\n"), $3;
+                       } else {
+                               printf "%s\n", $_;
+                       }
+               '                                               >> ipsec
+       done
+fi
 
 #
 # Kerberos configuration
 #
 if [ -x /usr/bin/klist ]; then
        echo "#"                                        >  kerberos
-       echo "# klist -e -c -A -f -a -n"                >> kerberos
+       echo "# klist --verbose --all-content"          >> kerberos
+       echo "#"                                        >> kerberos
+       klist --verbose --all-content                   >> kerberos     2>&1
+
        echo "#"                                        >> kerberos
-       ${PRIV} klist -e -c -A -f -a -n                 >> kerberos     2>&1
+       echo "# ktutil list"                            >> kerberos
+       echo "#"                                        >> kerberos
+       ${PRIV} /usr/sbin/ktutil --verbose list         >> kerberos     2>&1
 
        echo "#"                                        >> kerberos
-       echo "# klist -e -k -t -K"                      >> kerberos
+       echo "# gsstool list --verbose"                 >> kerberos
        echo "#"                                        >> kerberos
-       ${PRIV} klist -e -k -t -K                       >> kerberos     2>&1
+       /System/Library/PrivateFrameworks/Heimdal.framework/Helpers/gsstool list --verbose >> kerberos  2>&1
 fi
 
 #
-# BTMM configuration
+# system profiler
 #
+if [ -x /usr/sbin/system_profiler ]; then
+       system_profiler -xml    SPEthernetDataType      \
+                               SPFibreChannelDataType  \
+                               SPFireWireDataType      \
+                               SPFirewallDataType      \
+                               SPModemDataType         \
+                               SPNetworkDataType       \
+                               SPThunderboltDataType   \
+                               SPWWANDataType          \
+                               SPAirPortDataType       > system_profiler.spx   2>/dev/null
+fi
 
-BTMM_CLEANUP()
-{
-       rm -f .btmmfifo .btmminfo .digsync
-}
-
-BTMM_SETUP()
-{
-       BTMM_CLEANUP
-       mkfifo .btmmfifo
+#
+# system usage statistics
+#
+echo -n ""                                             > system-statistics
 
-       BTMMPORT=40000
-       while nc -6z ::1 "${PORT}"                      > /dev/null     2>&1
-       do
-               BTMMPORT=$((PORT + 1))
-       done
-}
+if [ -x /usr/bin/uptime ]; then
+       echo "#"                                        >> system-statistics
+       echo "# uptime"                                 >> system-statistics
+       echo "#"                                        >> system-statistics
+       /usr/bin/uptime                                 >> system-statistics    2>&1
+fi
 
-BTMM_CHECKMACDOTCOM()
-{
-       TAIL=`echo "${1}" | cut -d. -f2-`
-       if [ "${TAIL}" = "members.mac.com" ]; then
-               return 0
-       fi
+if [ -x /usr/sbin/sysctl ]; then
+       echo "#"                                        >> system-statistics
+       echo "# sysctl -a"                              >> system-statistics
+       echo "#"                                        >> system-statistics
+       /usr/sbin/sysctl -a                             >> system-statistics    2>&1
+fi
 
-       return 1
-}
+if [ -x /usr/bin/zprint ]; then
+       echo "#"                                        >> system-statistics
+       echo "# zprint"                                 >> system-statistics
+       echo "#"                                        >> system-statistics
+       ${PRIV} /usr/bin/zprint                         >> system-statistics    2>&1
+fi
 
-# get DNS info
-# params: QUERYNAME QUERYTYPE
-BTMM_DIG()
+#
+# collect executable and plugin info
+#
+report_binary_info()
 {
-       rm -f .digsync
+    if [ ! -f ${1} ]; then
+       return
+    fi
 
-       nc -6 -l "${BTMMPORT}" < .btmmfifo                      \
-       | openssl s_client      -connect "${HOSTPORT}" -quiet   > .btmmfifo     2>.digsync &
+    VERSION=`what ${1}`
+    echo "${VERSION}"                                  >> versions     2>&1
 
-       N_RETRY=0
-       while [ $N_RETRY -lt 50 -a ! -s .digsync ]
-       do
-               N_RETRY=$((N_RETRY + 1))
-               sleep 0.1
-       done
+    SUM=`sum ${1}`
+    echo "\tsum: ${SUM}"                               >> versions     2>&1
 
-       dig @::1        -p "${BTMMPORT}"                \
-                       -y "${TSIG}"                    \
-                       +short                          \
-                       +tcp                            \
-                       "${1}" "${2}"                   2>/dev/null
+    LSINFO=`ls -lu ${1}`
+    echo "\tadditional info: ${LSINFO}"                        >> versions     2>&1
 
-       wait %1
+    echo ""                                            >> versions     2>&1
 }
 
-# get the unique identifier used to lookup the keychain item for a zone
-# params: ZONE
-BTMM_UNIQUEIDFROMZONE()
+get_binary_info()
 {
-       BTMM_CHECKMACDOTCOM "${1}"
-       if [ $? -eq 0 ]; then
-               echo "dns:${1}"
-       else
-               echo "btmmdns:${1}"
-       fi
-}
+    for BIN in                                                                         \
+       /usr/libexec/bootpd                                                             \
+       /usr/libexec/configd                                                            \
+       /usr/sbin/mDNSResponder                                                         \
+       /usr/sbin/awacsd                                                                \
+       /usr/sbin/pppd                                                                  \
+       /usr/sbin/racoon                                                                \
+       /usr/libexec/misd                                                               \
+       /usr/libexec/InternetSharing                                                    \
+       /System/Library/Frameworks/SystemConfiguration.framework/SystemConfiguration    \
+
+    do
+       report_binary_info "${BIN}"
+    done
+
+    if [ -x /usr/bin/xcodebuild ]; then
+           /usr/bin/xcodebuild -showsdks                       \
+           | grep iphone                                       \
+           | awk '{print $NF}'                                 \
+           | while read IOS
+           do
+               SDKPATH="`xcrun --sdk $IOS --show-sdk-path`"
+               for BIN in                                                                              \
+                   /usr/libexec/configd_sim                                                            \
+                   /System/Library/Frameworks/SystemConfiguration.framework/SystemConfiguration        \
 
-# get hostname, port, TSIG name and TSIG data from keychain
-# params: UNIQUEID
-BTMM_GETINFO()
-{
-       ${PRIV} security find-generic-password          \
-               -s "${1}"                               \
-               -g /Library/Keychains/System.keychain   > .btmminfo     2>/dev/null
-       ${PRIV} security find-generic-password          \
-               -s "${1}"                               \
-               -g /Library/Keychains/System.keychain   \
-               2>&1 > /dev/null                        \
-       | sed -n 's/^password: \"\(.*\)\"$/\1/p'
+               do
+                   report_binary_info "${SDKPATH}${BIN}"
+               done
+           done
+    fi
 }
 
-# params: ZONE
-BTMM_URLISH()
+get_plugins_info()
 {
-       BTMM_CHECKMACDOTCOM "${1}"
-       if [ $? -eq 0 ]; then
-               echo "pm-members.mac.com.:443"
-       else
-               cat .btmminfo | sed -n 's/.*0x00000007 <blob>=\"\(.*\)\"/\1/p'
+    num=0
+    cd ${ROOT}/System/Library/SystemConfiguration
+    for PLUGIN in *.bundle
+    do
+       plugins[$num]=$PLUGIN
+       num=$(( $num + 1 ))
+    done
+
+    cd "${WORKDIR}"
+
+    for PLUGIN in "${plugins[@]}"
+    do
+       PLUGIN_DIR="${ROOT}/System/Library/SystemConfiguration/${PLUGIN}"
+       PLUGIN_INF=${PLUGIN_DIR}/Contents/Info.plist
+       if [ ! -f ${PLUGIN_INF} ]; then
+           PLUGIN_INF=${PLUGIN_DIR}/Info.plist
+           if [ ! -f ${PLUGIN_INF} ]; then
+               echo "${PLUGIN_INF}: No Info.plist"             >> versions             2>&1
+           fi
        fi
-}
 
-BTMM_RELAYINFO()
-{
-       BTMM_CHECKMACDOTCOM "${1}"
+       echo "${PLUGIN}"                                        >> versions             2>&1
+
+       ENABLED="Enabled"
+       BOOL=`scutil --get ${PLUGIN_INF} / Enabled                                      2>/dev/null`
        if [ $? -eq 0 ]; then
-               return
+           if [ ${BOOL} = "TRUE" ]; then
+               ENABLED="Enabled*"
+           else
+               ENABLED="Disabled"
+           fi
        fi
+       echo "\t${ENABLED}"                                     >> versions             2>&1
 
-       SECRET=`BTMM_GETINFO "btmmrelay:${1}"`
-
-       if [ -z "${SECRET}" ]; then
-               echo "  No Relay keychain item."                >> btmm
-               return
+       VERBOSE=""
+       BOOL=`scutil --get ${PLUGIN_INF} / Verbose                                      2>/dev/null`
+       if [ $? -eq 0 ]; then
+           if [ ${BOOL} = "TRUE" ]; then
+               VERBOSE="Verbose"
+           fi
        fi
-
-       if [ `echo "${SECRET}" | wc -l` -ne 1 ]; then
-               echo "  More than one Relay keychain item."     >> btmm
-               return
+       if [ -n "${VERBOSE}" ]; then
+               echo "\t${VERBOSE}"                             >> versions             2>&1
        fi
 
-       URLISH=`BTMM_URLISH "${DOMAIN}"`
-       ACCOUNT=`cat .btmminfo | sed -n 's/.*\"acct\"<blob>=\"\(.*\)\"/\1/p'`
-       KEYHASH="`perl -M'Digest::SHA1 qw(sha1_hex)' -l -e '
-                       printf "[SHA1:%s]\n", sha1_hex($ARGV[0] . "\n");
-       ' ${SECRET}`"
-       echo "  RHP: ${URLISH}"                                 >> btmm
-       echo "  RAC: ${ACCOUNT}"                                >> btmm
-       echo "  RKY: ${KEYHASH}"                                >> btmm
-}
-
-BTMM_REPORTZONE()
-{
-       DOMAIN="${1}"
+       VERSION=`scutil --get ${PLUGIN_INF} / CFBundleVersion                           2>/dev/null`
+       if [ $? -eq 1 ]; then
+               VERSION=`scutil --get ${PLUGIN_INF} / CFBundleShortVersionString        2>/dev/null`
+       fi
+       echo "\tVersion: ${VERSION}"                            >> versions             2>&1
 
-       echo                                                    >> btmm
-       echo "${DOMAIN}"                                        >> btmm
+       if [ -f ${PLUGIN_DIR}/Contents/MacOS/${PLUGIN%.*} ]; then
+           SUM=`sum ${PLUGIN_DIR}/Contents/MacOS/${PLUGIN%.*}`
+           echo "\tsum: ${SUM}"                                >> versions             2>&1
 
-       DNSID=`BTMM_UNIQUEIDFROMZONE "${DOMAIN}"`
-       SECRET=`BTMM_GETINFO "${DNSID}"`
+           LSINFO=`ls -lu ${PLUGIN_DIR}/Contents/MacOS/${PLUGIN%.*}`
+           echo "\tadditional info: ${LSINFO}"                 >> versions             2>&1
+       elif [ -f ${PLUGIN_DIR}/${PLUGIN%.*} ]; then
+           SUM=`sum ${PLUGIN_DIR}/${PLUGIN%.*}`
+           echo "\tsum: ${SUM}"                                >> versions             2>&1
 
-       if [ -z "${SECRET}" ]; then
-               echo "  No DNS keychain item."                  >> btmm
-               return
+           LSINFO=`ls -lu ${PLUGIN_DIR}/${PLUGIN%.*}`
+           echo "\tadditional info: ${LSINFO}"                 >> versions             2>&1
        fi
 
-       if [ `echo "${SECRET}" | wc -l` -ne 1 ]; then
-               echo "  More than one DNS keychain item."       >> btmm
-               return
-       fi
+       echo ""                                                 >> versions             2>&1
+    done
+}
 
-       URLISH=`BTMM_URLISH "${DOMAIN}"`
-       HOSTPORT=`echo "${URLISH}" | cut -d@ -f2`
-       ACCOUNT=`cat .btmminfo | sed -n 's/.*\"acct\"<blob>=\"\(.*\)\"/\1/p'`
-       TSIG="${ACCOUNT}:${SECRET}"
-
-       KEYHASH="`perl -M'Digest::SHA1 qw(sha1_hex)' -l -e '
-                       printf "[SHA1:%s]\n", sha1_hex($ARGV[0] . "\n");
-               ' ${SECRET}`"
-       echo ""                                                 >> btmm
-       echo "  DHP: ${URLISH}"                                 >> btmm
-       echo "  DAC: ${ACCOUNT}"                                >> btmm
-       echo "  DKY: ${KEYHASH}"                                >> btmm
-
-       BTMM_RELAYINFO "${DOMAIN}"
-
-       REACHHOST=`echo "${HOSTPORT}" | cut -d: -f1`
-       STATUSES=`scutil -r "${REACHHOST}"`
-       for REACHSTATUS in `echo ${STATUSES} | tr -d ' ' | tr ',' ' '`; do
-               if [ "$REACHSTATUS" == "NotReachable" ] \
-                       || [ "$REACHSTATUS" == "ConnectionRequired" ]; then
-                       echo "  Skipping DNS queries, no connectivity"  >> btmm
-                       return
-               fi
-       done
+if [ -x /usr/bin/what -a -x /usr/bin/sum -a -x /bin/ls ]; then
+       get_binary_info
+       get_plugins_info
+fi
 
-       for TYPE in                     \
-               _afpovertcp._tcp        \
-               _airport._tcp           \
-               _adisk._tcp             \
-               _http._tcp              \
-               _rfb._tcp               \
-               _smb._tcp               \
-               _ssh._tcp
-       do
-               BTMM_DIG "${TYPE}.${DOMAIN}" ptr        \
-               | while read -r REG
-               do
-                       echo ""                                 >> btmm
-                       /bin/echo "  ${REG}"                    >> btmm
-                       echo ""                                 >> btmm
-
-                       INF_Q=`/bin/echo "${REG}" | sed -e "s/${TYPE}/_device-info._tcp/"`
-                       INF=`BTMM_DIG "${INF_Q}" txt`
-                       echo "    INF: ${INF}"                  >> btmm
-
-                       SRV=`BTMM_DIG ${REG} srv`
-                       SRV1=`/bin/echo "${SRV}" | head -1`
-                       echo "    SRV: ${SRV1}"                 >> btmm
-                       SRV2=`/bin/echo "${SRV}" | tail +2`
-                       if [ -n "${SRV2}" ]; then
-                               SRV="${SRV1}"
-                               /bin/echo "${SRV2}"             \
-                               | sed -e 's/^/  *****: /'       >> btmm
-                       fi
+#
+# Last thing is to collect the logs to give a chance for networkd and mDNSResponder
+# to finish dumping their state
+#
 
-                       TXT=`BTMM_DIG ${REG} txt`
-                       TXT1=`/bin/echo "${TXT}" | head -1`
-                       echo "    TXT: ${TXT1}"                 >> btmm
-                       TXT2=`/bin/echo "${TXT}" | tail +2`
-                       if [ -n "${TXT2}" ]; then
-                               /bin/echo "${TXT2}"             \
-                               | sed -e 's/^/  *****: /'       >> btmm
-                       fi
+#
+# system log, kernel.log, early boot log messages
+#
+if [ -x /usr/bin/syslog ]; then
+       # save the recent activity
+       ${PRIV} /usr/bin/syslog | ${TAIL_25000}                         > syslog
 
-                       HOST=`/bin/echo "${SRV}" | cut -d ' ' -f 4-`
-                       if [ -n "${HOST}" ]; then
-                               V4=`BTMM_DIG ${HOST} a`
-                               V6=`BTMM_DIG ${HOST} aaaa`
-                               KRB=`BTMM_DIG _kerberos.${HOST} txt`
-                               TUN=`BTMM_DIG _autotunnel._udp.${HOST} srv`
-                               AT6=`BTMM_DIG _autotunnel6.${HOST} aaaa`
-                       else
-                               V4=""
-                               V6=""
-                               KRB=""
-                               TUN=""
-                               AT6=""
-                       fi
-                       if [ -n "${V4}" ]; then
-                               echo "     v4: ${V4}"           >> btmm
-                       fi
-                       if [ -n "${V6}" ]; then
-                               echo "     v6: ${V6}"           >> btmm
-                       fi
-                       if [ -n "${KRB}" ]; then
-                               echo "    KRB: ${KRB}"          >> btmm
-                       fi
-                       if [ -n "${TUN}" ]; then
-                               echo "    TUN: ${TUN}"          >> btmm
-
-                               HOST=`/bin/echo "${TUN}" | cut -d ' ' -f 4-`
-                               if [ -n "${HOST}" ]; then
-                                       V4=`BTMM_DIG ${HOST} a`
-                                       V6=`BTMM_DIG ${HOST} aaaa`
-                               fi
-                               if [ -n "${V4}" ]; then
-                                       echo "     v4: ${V4}"   >> btmm
-                               fi
-                               if [ -n "${V6}" ]; then
-                                       echo "     v6: ${V6}"   >> btmm
-                               fi
-                       fi
-                       if [ -n "${AT6}" ]; then
-                               echo "    AT6: ${AT6}"          >> btmm
-                       fi
-               done
-       done
-}
+       # save just the "kernel" activity (in case some of the
+       # interesting/relevant message are before the messages
+       # captured above.
+       ${PRIV} /usr/bin/syslog -k Facility kern | ${TAIL_25000}        > kernel
 
-BTMM_SETUP
+       if [ -d /var/log/DiagnosticMessages ]; then
+               # save any MessageTracer activity
+               ${PRIV} /usr/bin/syslog -d /var/log/DiagnosticMessages  \
+                                       -F raw                          \
+                                       -T local                        \
+                       | ${TAIL_25000}                                 > DiagnosticMessages
+       fi
+else
+       if [ -f /var/log/system.log ]; then
+               ${PRIV} ${TAIL_25000} /var/log/system.log               > system.log
+       fi
+       if [ -f /var/log/kernel.log ]; then
+               ${PRIV} ${TAIL_25000} /var/log/kernel.log               > kernel.log
+       fi
+fi
+if [ -x /sbin/dmesg ]; then
+       ${PRIV} /sbin/dmesg                                             > dmesg
+fi
 
-scutil <<_END_OF_INPUT \
-| sed -n 's@.* : *\(.*\)$@\1@p' \
-| sort \
-| while read DOMAIN
+#
+# IPConfiguration log
+#
+if [ -f /var/log/com.apple.IPConfiguration.bootp ]; then
+       ${PRIV} ${TAIL_2000} /var/log/com.apple.IPConfiguration.bootp   \
+                                                       > com.apple.IPConfiguration.bootp
+fi
+
+#
+# ppp log file(s)
+#
+scutil <<_END_OF_INPUT                         \
+| awk -F' *: *'                                        \
+    '                                          \
+     /Logfile : / {                            \
+       if (index($2, "/") == 1) { print $2 }   \
+       else { print "/var/log/ppp/" $2 }       \
+     }                                         \
+     END {                                     \
+       print "/tmp/pppotcp.log"                        \
+     }                                         \
+    '                                          \
+| sort -u                                      \
+| while read logFile
 open
-show Setup:/Network/BackToMyMac
+show Setup:/Network/Service/[^/]+/PPP pattern
 quit
 _END_OF_INPUT
 do
-       BTMM_REPORTZONE "$DOMAIN"
+       if [ -f "${logFile}" ]; then
+               b="`basename ${logFile}`"
+               cat "${logFile}"                        > "${b}"                2>&1
+       fi
 done
 
-BTMM_CLEANUP
-
 #
-# collect crash reports
+# application firewall log
 #
-for daemon in                          \
-               bootpd                  \
-               configd                 \
-               eapolclient             \
-               mDNSResponder           \
-               mDNSResponderHelper     \
-               awacsd                  \
-               pppd                    \
-               racoon                  \
-               socketfilterfw          \
-               InternetSharing         \
-               SCHelper                \
-               SCMonitor               \
+if [ -f /var/log/appfirewall.log ]; then
+       ${PRIV} ${TAIL_2000} /var/log/appfirewall.log   > appfirewall.log
+fi
+
+if [ -x /bin/ls ]; then
+       #
+       # collect crash reports
+       #
+       for daemon in                           \
+                       bootpd                  \
+                       configd                 \
+                       eapolclient             \
+                       mDNSResponder           \
+                       mDNSResponderHelper     \
+                       awacsd                  \
+                       pppd                    \
+                       racoon                  \
+                       socketfilterfw          \
+                       InternetSharing         \
+                       SCHelper                \
+                       SCMonitor               \
 
-do
-       /bin/ls -1      /Library/Logs/DiagnosticReports/${daemon}_*.crash       \
-                       /Library/Logs/CrashReporter/${daemon}_*.crash           \
-                       /Library/Logs/CrashReporter/${daemon}_*.plist           \
-                       2>/dev/null                                             \
+       do
+               /bin/ls -1      /Library/Logs/DiagnosticReports/${daemon}_*.crash       \
+                               /Library/Logs/CrashReporter/${daemon}_*.crash           \
+                               /Library/Logs/CrashReporter/${daemon}_*.plist           \
+                               2>/dev/null                                             \
+               | while read log
+               do
+                       if [ -f "${log}" ]; then
+                               b="`basename ${log}`"
+                               ${PRIV} cat "${log}"            > "${b}"                2>&1
+                       fi
+               done
+       done
+
+       #
+       # collect any verbose logging output
+       #
+       /bin/ls -1      /Library/Logs/CrashReporter/com.apple.networking.*.log*         \
+                       2>/dev/null                                                     \
        | while read log
        do
                if [ -f "${log}" ]; then
                        b="`basename ${log}`"
-                       ${PRIV} cat "${log}"            > "${b}"                2>&1
+                       ${PRIV} cat "${log}"                    > "${b}"                2>&1
                fi
        done
-done
-
-#
-# system profiler
-#
-if [ -x /usr/sbin/system_profiler ]; then
-       system_profiler -xml    SPEthernetDataType      \
-                               SPFibreChannelDataType  \
-                               SPFireWireDataType      \
-                               SPFirewallDataType      \
-                               SPModemDataType         \
-                               SPNetworkDataType       \
-                               SPThunderboltDataType   \
-                               SPWWANDataType          \
-                               SPAirPortDataType       > system_profiler.spx   2>&1
 fi
 
-#
-# system usage statistics
-#
-echo "#"                                               >  system-statistics
-echo "# uptime"                                                >> system-statistics
-echo "#"                                               >> system-statistics
-uptime                                                 >> system-statistics    2>&1
-
-echo "#"                                               >> system-statistics
-echo "# sysctl -a"                                     >> system-statistics
-echo "#"                                               >> system-statistics
-sysctl -a                                              >> system-statistics    2>&1
-
-echo "#"                                               >> system-statistics
-echo "# zprint"                                                >> system-statistics
-echo "#"                                               >> system-statistics
-zprint                                                 >> system-statistics    2>&1
-
-echo "#"                                               >> system-statistics
-echo "# top -l5 -s2"                                   >> system-statistics
-echo "#"                                               >> system-statistics
-top -s 2 -l 5                                          >> system-statistics    2>&1
 
 #
 # collect everything into a single archive
 #
 cd "${WORKDIR}/.."
-if [ -x /usr/bin/tar ]; then
-       tar -c ${GZ_OPT} -f "${ARCHIVE}" "${OUT}"
-else
-       pax -w ${GZ_OPT} -f "${ARCHIVE}" "${OUT}"
-fi
+tar -c ${GZ_OPT} -f "${ARCHIVE}" "${OUT}"
 rm -rf "${WORKDIR}"
 
 if [ ${UID} -eq 0 ]; then
@@ -869,10 +859,3 @@ fi
 
 echo "Network data collected to \"${ARCHIVE}\""
 
-#
-# if requested, generate a crash report
-#
-if [ "${OUTDIR}" = "/Library/Logs/CrashReporter/SystemConfiguration" -a "${1}" = "CRASH" ]; then
-       kill -ABRT $$
-fi
-
diff --git a/libSystemConfiguration/libSystemConfiguration_client.c b/libSystemConfiguration/libSystemConfiguration_client.c
new file mode 100644 (file)
index 0000000..5023329
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2012, 2013 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 <Availability.h>
+#include <TargetConditionals.h>
+#include <asl.h>
+#include <dispatch/dispatch.h>
+#include <vproc.h>
+#include <vproc_priv.h>
+#include <xpc/xpc.h>
+
+#include "libSystemConfiguration_client.h"
+
+
+#pragma mark -
+#pragma mark libSC fork handlers
+
+
+__attribute__((weak_import)) bool _dispatch_is_multithreaded(void);
+
+static boolean_t _has_forked = FALSE;
+
+// These functions are registered with libSystem to
+// handle pthread_atfork callbacks.
+
+void
+_libSC_info_fork_prepare()
+{
+       return;
+}
+
+void
+_libSC_info_fork_parent()
+{
+       return;
+}
+
+void
+_libSC_info_fork_child()
+{
+       if (_dispatch_is_multithreaded()) {
+               // if dispatch was active before fork
+               _has_forked = TRUE;
+       }
+
+       return;
+}
+
+
+#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);
+       asl_log(NULL, NULL, ASL_LEVEL_ERR, "%s = %s", msg, desc);
+       free(desc);
+}
+
+
+__private_extern__
+libSC_info_client_t *
+libSC_info_client_create(dispatch_queue_t      q,
+                        const char             *service_name,
+                        const char             *service_description)
+{
+       xpc_connection_t        c;
+       libSC_info_client_t     *client;
+#if    !TARGET_IPHONE_SIMULATOR
+       const uint64_t          flags   =       XPC_CONNECTION_MACH_SERVICE_PRIVILEGED;
+#else  // !TARGET_IPHONE_SIMULATOR
+       const uint64_t          flags   =       0;
+#endif // !TARGET_IPHONE_SIMULATOR
+
+       if (_has_forked) {
+               return NULL;
+       }
+
+       client = malloc(sizeof(libSC_info_client_t));
+       client->active = TRUE;
+       client->service_description = strdup(service_description);
+       client->service_name = strdup(service_name);
+
+       c = xpc_connection_create_mach_service(service_name, q, flags);
+
+       xpc_connection_set_event_handler(c, ^(xpc_object_t xobj) {
+               xpc_type_t      type;
+
+               type = xpc_get_type(xobj);
+               if (type == XPC_TYPE_DICTIONARY) {
+                       asl_log(NULL, NULL, ASL_LEVEL_ERR, "%s: unexpected message", client->service_name);
+                       log_xpc_object("  dict = ", xobj);
+               } else if (type == XPC_TYPE_ERROR) {
+                       if (xobj == XPC_ERROR_CONNECTION_INVALID) {
+                               asl_log(NULL, NULL, ASL_LEVEL_ERR, "%s: server not available", client->service_name);
+                               client->active = FALSE;
+                       } else if (xobj == XPC_ERROR_CONNECTION_INTERRUPTED) {
+                               asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "%s: server failed", client->service_name);
+                       } else {
+                               const char      *desc;
+
+                               desc = xpc_dictionary_get_string(xobj, XPC_ERROR_KEY_DESCRIPTION);
+                               asl_log(NULL, NULL, ASL_LEVEL_DEBUG,
+                                       "%s: connection error: %d : %s",
+                                       client->service_name,
+                                       xpc_connection_get_pid(c),
+                                       desc);
+                       }
+
+               } else {
+                       asl_log(NULL, NULL, ASL_LEVEL_ERR,
+                               "%s: unknown event type : %p",
+                               client->service_name,
+                               type);
+               }
+       });
+
+       client->connection = c;
+
+       xpc_connection_resume(c);
+
+       return client;
+}
+
+
+__private_extern__
+void
+libSC_info_client_release(libSC_info_client_t *client)
+{
+       xpc_release(client->connection);
+       free(client->service_description);
+       free(client->service_name);
+       free(client);
+}
+
+
+__private_extern__
+xpc_object_t
+libSC_send_message_with_reply_sync(libSC_info_client_t *client,
+                                  xpc_object_t         message)
+{
+       xpc_object_t    reply;
+
+       while (TRUE) {
+               // send request to the DNS configuration server
+               reply = xpc_connection_send_message_with_reply_sync(client->connection, message);
+               if (reply != NULL) {
+                       xpc_type_t      type;
+
+                       type = xpc_get_type(reply);
+                       if (type == XPC_TYPE_DICTIONARY) {
+                               // reply available
+                               break;
+                       }
+
+                       if ((type == XPC_TYPE_ERROR) && (reply == XPC_ERROR_CONNECTION_INTERRUPTED)) {
+                               asl_log(NULL, NULL, ASL_LEVEL_DEBUG,
+                                       "%s server failure, retrying",
+                                       client->service_description);
+                               // retry request
+                               xpc_release(reply);
+                               continue;
+                       }
+
+                       if ((type == XPC_TYPE_ERROR) && (reply == XPC_ERROR_CONNECTION_INVALID)) {
+                               asl_log(NULL, NULL, ASL_LEVEL_ERR,
+                                       "%s server not available",
+                                       client->service_description);
+                               client->active = FALSE;
+                       } else {
+                               asl_log(NULL, NULL, ASL_LEVEL_ERR,
+                                       "%s xpc_connection_send_message_with_reply_sync() with unexpected reply",
+                                       client->service_description);
+                               log_xpc_object("  reply", reply);
+                       }
+
+                       xpc_release(reply);
+                       reply = NULL;
+                       break;
+               }
+       }
+
+       return reply;
+}
diff --git a/libSystemConfiguration/libSystemConfiguration_client.h b/libSystemConfiguration/libSystemConfiguration_client.h
new file mode 100644 (file)
index 0000000..c93d477
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2012, 2013 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@
+ */
+
+#ifndef _LIBSYSTEMCONFIGURATION_CLIENT_H
+#define _LIBSYSTEMCONFIGURATION_CLIENT_H
+
+#include <Availability.h>
+#include <TargetConditionals.h>
+#include <sys/cdefs.h>
+#include <dispatch/dispatch.h>
+#include <xpc/xpc.h>
+
+// ------------------------------------------------------------
+
+#pragma mark -
+#pragma mark [XPC] DNS configuration server
+
+#define        DNSINFO_SERVER_VERSION          20130408
+
+#if    !TARGET_IPHONE_SIMULATOR
+#define        DNSINFO_SERVICE_NAME            "com.apple.SystemConfiguration.DNSConfiguration"
+#else  // !TARGET_IPHONE_SIMULATOR
+#define        DNSINFO_SERVICE_NAME            "com.apple.SystemConfiguration.DNSConfiguration_sim"
+#endif // !TARGET_IPHONE_SIMULATOR
+
+#define        DNSINFO_PROC_NAME               "proc_name"     // string
+
+#define        DNSINFO_REQUEST                 "request_op"    // int64
+
+enum {
+       DNSINFO_REQUEST_COPY            = 0x10001,
+       DNSINFO_REQUEST_ACKNOWLEDGE,
+};
+
+#define        DNSINFO_CONFIGURATION           "configuration" // data
+#define        DNSINFO_GENERATION              "generation"    // uint64
+
+// ------------------------------------------------------------
+
+#pragma mark -
+#pragma mark [XPC] Network information (nwi) server
+
+#define        NWI_SERVER_VERSION              20130408
+
+#if    !TARGET_IPHONE_SIMULATOR
+#define        NWI_SERVICE_NAME                "com.apple.SystemConfiguration.NetworkInformation"
+#else  // !TARGET_IPHONE_SIMULATOR
+#define        NWI_SERVICE_NAME                "com.apple.SystemConfiguration.NetworkInformation_sim"
+#endif // !TARGET_IPHONE_SIMULATOR
+
+#define        NWI_PROC_NAME                   "proc_name"     // string
+
+#define        NWI_REQUEST                     "request_op"    // int64
+
+enum {
+       NWI_REQUEST_COPY                = 0x20001,
+       NWI_REQUEST_ACKNOWLEDGE,
+};
+
+#define        NWI_CONFIGURATION               "configuration" // data
+#define        NWI_GENERATION                  "generation"    // uint64
+
+// ------------------------------------------------------------
+
+typedef struct {
+       _Bool                   active;
+       xpc_connection_t        connection;
+       char                    *service_description;
+       char                    *service_name;
+} libSC_info_client_t;
+
+// ------------------------------------------------------------
+
+__BEGIN_DECLS
+
+libSC_info_client_t *
+libSC_info_client_create               (
+                                        dispatch_queue_t       q,
+                                        const char             *service_name,
+                                        const char             *service_description
+                                       );
+
+void
+libSC_info_client_release              (
+                                        libSC_info_client_t    *client
+                                       );
+
+xpc_object_t
+libSC_send_message_with_reply_sync     (
+                                        libSC_info_client_t    *client,
+                                        xpc_object_t           message
+                                       );
+
+__END_DECLS
+
+#endif // _LIBSYSTEMCONFIGURATION_CLIENT_H
diff --git a/libSystemConfiguration/libSystemConfiguration_server.c b/libSystemConfiguration/libSystemConfiguration_server.c
new file mode 100644 (file)
index 0000000..82a201a
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+ * Copyright (c) 2012, 2013 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 <Availability.h>
+#include <TargetConditionals.h>
+#include <asl.h>
+#include <dispatch/dispatch.h>
+#include <vproc.h>
+#include <vproc_priv.h>
+#include <xpc/xpc.h>
+#include <xpc/private.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SCPrivate.h>
+
+#include "libSystemConfiguration_server.h"
+
+#define kTrailingEdgeAgentEntitlement "com.apple.SystemConfiguration.trailing-edge-agent"
+
+#pragma mark -
+#pragma mark Support functions
+
+
+//__private_extern__ void
+//log_xpc_object(const char *msg, xpc_object_t obj)
+//{
+//     char    *desc;
+//
+//     desc = xpc_copy_description(obj);
+//     asl_log(NULL, NULL, ASL_LEVEL_ERR, "%s = %s", msg, desc);
+//     free(desc);
+//}
+
+
+#pragma mark -
+#pragma mark client connection trackng
+
+
+typedef struct {
+       xpc_connection_t        connection;
+} client_key_t;
+
+typedef struct {
+       pid_t                   pid;
+       uint64_t                generation_pushed;
+       uint64_t                generation_acknowledged;
+} client_val_t;
+
+
+static __inline__ CF_RETURNS_RETAINED CFDataRef
+_client_key(xpc_connection_t c)
+{
+       client_key_t    key;
+       CFDataRef       client_key;
+
+       key.connection = c;
+       client_key = CFDataCreate(NULL, (UInt8 *)&key, sizeof(key));
+       return client_key;
+}
+
+
+#if    ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 60000))
+static void
+_handle_entitlement_check_failure(pid_t pid)
+{
+       static Boolean                  cleanupScheduled        = FALSE;
+       static dispatch_once_t          initializer             = 0;
+       static CFMutableArrayRef        pids                    = NULL;
+       static dispatch_queue_t         queue                   = NULL;
+
+       dispatch_once(&initializer, ^{
+               pids = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
+               queue = dispatch_queue_create("handle unentitled ack", NULL);
+       });
+
+       dispatch_sync(queue, ^{
+               CFNumberRef     pidNumber       = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &pid);
+
+               if (!CFArrayContainsValue(pids, CFRangeMake(0, CFArrayGetCount(pids)), pidNumber)) {
+                       CFArrayAppendValue(pids, pidNumber);
+
+                       SCLog(TRUE, LOG_ERR, CFSTR("DNS/nwi dropping ack w/no entitlement, pid = %d"), pid);
+
+                       if (!cleanupScheduled) {
+                               cleanupScheduled = TRUE;
+                               dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 180LL * NSEC_PER_SEC), queue, ^{
+                                       CFArrayRemoveAllValues(pids);
+                                       cleanupScheduled = FALSE;
+                               });
+                       }
+               }
+
+               CFRelease(pidNumber);
+       });
+}
+#endif // ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 60000))
+
+
+/*
+ * libSystemConfiguraiton_client
+ *
+ * - all APIs must be called from the same [serial] dispatch queue
+ */
+
+
+__private_extern__
+void
+_libSC_info_server_init(libSC_info_server_t *server_info) {
+       bzero(server_info, sizeof(*server_info));
+       server_info->info = CFDictionaryCreateMutable(NULL,
+                                                     0,
+                                                     &kCFTypeDictionaryKeyCallBacks,
+                                                     &kCFTypeDictionaryValueCallBacks);
+       return;
+}
+
+
+__private_extern__
+void
+_libSC_info_server_set_data(libSC_info_server_t        *server_info,
+                           CFDataRef           data,
+                           uint64_t            generation)
+{
+       // update stored configuration
+       if (server_info->data != NULL) {
+               CFRelease(server_info->data);
+               server_info->data = NULL;
+       }
+       if (data != NULL) {
+               CFRetain(data);
+               server_info->data = data;
+       }
+
+       // update generation
+       if (generation == 0) {
+               // generation must be non-zero
+               generation = 1;
+       }
+       server_info->generation = generation;
+
+       // new configuration, all ack'ing clients need to
+       // check-in again
+       server_info->inSync_NO += server_info->inSync_YES;
+       server_info->inSync_YES = 0;
+
+       return;
+}
+
+
+/*
+ * _libSC_info_server_in_sync
+ *
+ * Called to check if all of the "active" configuration [XPC] connection
+ * are in sync with the requested generation.
+ */
+__private_extern__
+Boolean
+_libSC_info_server_in_sync(libSC_info_server_t *server_info)
+{
+       return (server_info->inSync_NO == 0) ? TRUE : FALSE;
+}
+
+
+/*
+ * _libSC_info_server_open
+ *
+ * Called when a new configuration [XPC] connection
+ * is established.
+ *
+ * - tracks the last generation pushed to the caller and
+ *   the last generation ack'd by the caller
+ */
+__private_extern__
+void
+_libSC_info_server_open(libSC_info_server_t    *server_info,
+                       xpc_connection_t        c)
+{
+       CFDataRef       client_key;
+       CFDataRef       client_val;
+       client_val_t    val;
+
+       client_key = _client_key(c);
+
+       val.pid                     = xpc_connection_get_pid(c);
+       val.generation_pushed       = 0;
+       val.generation_acknowledged = 0;
+       client_val = CFDataCreate(NULL, (UInt8 *)&val, sizeof(val));
+
+       CFDictionarySetValue(server_info->info, client_key, client_val);
+       CFRelease(client_key);
+       CFRelease(client_val);
+
+       return;
+}
+
+
+/*
+ * _libSC_info_server_get_data
+ *
+ * Called when a [XPC] connection wants the current configuration.
+ *
+ * - updates the last generation pushed to the caller
+ */
+__private_extern__
+CFDataRef
+_libSC_info_server_get_data(libSC_info_server_t        *server_info,
+                           xpc_connection_t    c,
+                           uint64_t            *generation)
+{
+       CFDataRef       client_key;
+       CFDataRef       client_val;
+       client_val_t    *val;
+
+       // update last generation pushed to client
+       client_key = _client_key(c);
+       client_val = CFDictionaryGetValue(server_info->info, client_key);
+       CFRelease(client_key);
+
+       val = (client_val_t *)(void *)CFDataGetBytePtr(client_val);
+       val->generation_pushed = server_info->generation;
+
+       // return generation
+       *generation = server_info->generation;
+       if (*generation == 1) {
+               *generation = 0;
+       }
+
+       // return data
+       return server_info->data;
+}
+
+
+/*
+ * _libSC_info_server_acknowledged
+ *
+ * Called when a [XPC] connection wants to acknowledge a
+ * processed configuration.
+ *
+ * - updates the last generation ack'd by the caller
+ * - updates the count of [XPC] connections that are / not in sync
+ */
+__private_extern__
+Boolean
+_libSC_info_server_acknowledged(libSC_info_server_t    *server_info,
+                               xpc_connection_t        c,
+                               uint64_t                generation)
+{
+       CFDataRef       client_key;
+       CFDataRef       client_val;
+#if    ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 60000))
+       xpc_object_t    ent_value;
+       Boolean         entitled        = FALSE;
+#endif // ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 60000))
+       Boolean         sync_updated    = FALSE;
+       client_val_t    *val;
+
+#if    ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 60000))
+       ent_value = xpc_connection_copy_entitlement_value(c, kTrailingEdgeAgentEntitlement);
+       if (ent_value != NULL) {
+               if (xpc_get_type(ent_value) == XPC_TYPE_BOOL) {
+                       entitled = xpc_bool_get_value(ent_value);
+               }
+               xpc_release(ent_value);
+       }
+
+       if (!entitled) {
+               _handle_entitlement_check_failure(xpc_connection_get_pid(c));
+               return FALSE;
+       }
+#endif // ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 60000))
+
+       client_key = _client_key(c);
+       client_val = CFDictionaryGetValue(server_info->info, client_key);
+       CFRelease(client_key);
+
+       val = (client_val_t *)(void *)CFDataGetBytePtr(client_val);
+
+       if (val->generation_acknowledged == 0) {
+               // if first ack
+               if (generation == server_info->generation) {
+                       server_info->inSync_YES++;
+               } else {
+                       server_info->inSync_NO++;
+                       sync_updated = TRUE;
+               }
+       } else if ((generation != val->generation_acknowledged) &&
+                   (generation == server_info->generation)) {
+               // if we've previously ack'd a configuration
+               // ... and if we are ack'ing a configuration
+               //     that we have not previously ack'd
+               // ... and if we're ack'ing the current stored
+               //     configuration
+               server_info->inSync_NO--;
+               server_info->inSync_YES++;
+               sync_updated = TRUE;
+       }
+
+       val->generation_acknowledged = generation;
+
+       return sync_updated;
+}
+
+
+/*
+ * _libSC_info_server_close
+ *
+ * Called when a configuration [XPC] connection is closed.
+ */
+__private_extern__
+Boolean
+_libSC_info_server_close(libSC_info_server_t   *server_info,
+                        xpc_connection_t       c)
+{
+       CFDataRef       client_key;
+       CFDataRef       client_val;
+       Boolean         sync_updated    = FALSE;
+
+       client_key = _client_key(c);
+
+       // get client info, remove ack'd info
+       client_val = CFDictionaryGetValue(server_info->info, client_key);
+       if (client_val != NULL) {
+               client_val_t    *val;
+
+               val = (client_val_t *)(void *)CFDataGetBytePtr(client_val);
+               if (val->generation_acknowledged > 0) {
+                       // if we've previously ack'd a configuration
+                       if (val->generation_acknowledged == server_info->generation) {
+                               // if currently in sync
+                               server_info->inSync_YES--;
+                       } else {
+                               // if currently NOT in sync
+                               server_info->inSync_NO--;
+                               sync_updated = TRUE;
+                       }
+               }
+       }
+
+       CFDictionaryRemoveValue(server_info->info, client_key);
+       CFRelease(client_key);
+
+       return sync_updated;
+}
+
diff --git a/libSystemConfiguration/libSystemConfiguration_server.h b/libSystemConfiguration/libSystemConfiguration_server.h
new file mode 100644 (file)
index 0000000..4093bb7
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2012 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@
+ */
+
+#ifndef _LIBSYSTEMCONFIGURATION_SERVER_H
+#define _LIBSYSTEMCONFIGURATION_SERVER_H
+
+#include <Availability.h>
+#include <TargetConditionals.h>
+#include <sys/cdefs.h>
+#include <dispatch/dispatch.h>
+#include <xpc/xpc.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+// ------------------------------------------------------------
+
+#pragma mark -
+#pragma mark [XPC] information server common code
+
+// ------------------------------------------------------------
+
+
+/*
+ * libSC_info_server_t
+ *     data (CFData)
+ *             stored configuration
+ *     generation
+ *             generation of the last stored configuration
+ *     info (CFDictionary)
+ *             key = xpc_connection_t [CFData]
+ *             val = [CFData] (process name, last push'd, last ack'd)
+ *     inSync_NO, inSync_YES
+ *             count of client connections that have ack'd a configuration that
+ *             are (or are not) in sync with the last stored generation#
+*/
+typedef struct {
+       CFDataRef               data;
+       uint64_t                generation;
+       CFMutableDictionaryRef  info;
+       int                     inSync_NO;      // ack'ing clients not in sync w/generation
+       int                     inSync_YES;     // ack'ing clients in sync w/generation
+} libSC_info_server_t;
+
+
+__BEGIN_DECLS
+
+// Global server info SPIs
+
+void
+_libSC_info_server_init                (
+                                libSC_info_server_t    *server_info
+                               );
+
+Boolean
+_libSC_info_server_in_sync     (
+                                libSC_info_server_t    *server_info
+                               );
+
+void
+_libSC_info_server_set_data    (
+                                libSC_info_server_t    *server_info,
+                                CFDataRef              data,
+                                uint64_t               generation
+                               );
+
+// Per-session server info SPIs
+
+void
+_libSC_info_server_open                (
+                                libSC_info_server_t    *server_info,
+                                xpc_connection_t       c
+                               );
+
+CFDataRef
+_libSC_info_server_get_data    (
+                                libSC_info_server_t    *server_info,
+                                xpc_connection_t       c,
+                                uint64_t               *generation
+                               );
+
+Boolean
+_libSC_info_server_acknowledged        (
+                                libSC_info_server_t    *server_info,
+                                xpc_connection_t       c,
+                                uint64_t               generation
+                               );
+
+Boolean
+_libSC_info_server_close       (
+                                libSC_info_server_t    *server_info,
+                                xpc_connection_t       c
+                               );
+
+__END_DECLS
+
+#endif // _LIBSYSTEMCONFIGURATION_SERVER_H
index 18b4c6bee2021fbf1049cfde31ea01902445fd24..4153c001740d888b1b35133e0fffa6136f83f866 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2011-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #include <stdlib.h>
 #include <stdio.h>
 #include <sys/socket.h>
+#include <dispatch/dispatch.h>
+#include <xpc/xpc.h>
+
+#include "libSystemConfiguration_client.h"
 #include "network_information.h"
 #include "network_information_priv.h"
 
@@ -37,8 +41,30 @@ static boolean_t     nwi_store_token_valid   = FALSE;
 static pthread_once_t  initialized             = PTHREAD_ONCE_INIT;
 static int             nwi_store_token;
 
+static boolean_t       nwi_store_force_refresh = FALSE;
+
+#pragma mark -
+#pragma mark Network information [nwi] client support
+
+
+// Note: protected by __nwi_configuration_queue()
+static int                     nwi_active      = 0;
+static libSC_info_client_t     *nwi_client     = NULL;
+
+
+static dispatch_queue_t
+__nwi_configuration_queue()
+{
+       static dispatch_once_t  once;
+       static dispatch_queue_t q;
+
+       dispatch_once(&once, ^{
+               q = dispatch_queue_create(NWI_SERVICE_NAME, NULL);
+       });
+
+       return q;
+}
 
-/* Private */
 static
 void
 _nwi_state_initialize(void)
@@ -57,7 +83,7 @@ _nwi_state_initialize(void)
 
 static
 void
-nwi_set_alias(nwi_state* state, nwi_ifstate* ifstate)
+_nwi_set_alias(nwi_state* state, nwi_ifstate* ifstate)
 {
        nwi_ifstate*      ifstate_alias;
        int af = ifstate->af;
@@ -87,11 +113,15 @@ _nwi_state_reset_alias(nwi_state_t state) {
 
        for (i = state->ipv6_start;
             i < state->ipv6_start + state->ipv6_count; i++) {
-               nwi_set_alias(state, &state->nwi_ifstates[i]);
+               _nwi_set_alias(state, &state->nwi_ifstates[i]);
        }
 }
 
-/* Public APIs' */
+
+#pragma mark -
+#pragma mark Network information [nwi] APIs
+
+
 /*
  * Function: nwi_state_get_notify_key
  * Purpose:
@@ -105,12 +135,23 @@ _nwi_state_reset_alias(nwi_state_t state) {
 const char *
 nwi_state_get_notify_key()
 {
+#if    !TARGET_IPHONE_SIMULATOR
        return "com.apple.system.SystemConfiguration.nwi";
+#else  // !TARGET_IPHONE_SIMULATOR
+       return "com.apple.iOS_Simulator.SystemConfiguration.nwi";
+#endif // !TARGET_IPHONE_SIMULATOR
 }
 
+#define ATOMIC_CMPXCHG(p, o, n)        __sync_bool_compare_and_swap((p), (o), (n))
 #define ATOMIC_INC(p)          __sync_fetch_and_add((p), 1)            // return (n++);
 #define ATOMIC_DEC(p)          __sync_sub_and_fetch((p), 1)            // return (--n);
 
+void
+_nwi_state_force_refresh()
+{
+       ATOMIC_CMPXCHG(&nwi_store_force_refresh, FALSE, TRUE);
+}
+
 static void
 nwi_state_retain(nwi_state_t state)
 {
@@ -126,12 +167,102 @@ nwi_state_retain(nwi_state_t state)
 void
 nwi_state_release(nwi_state_t state)
 {
-       if (ATOMIC_DEC(&state->ref) == 0) {
-               free(state);
+       if (ATOMIC_DEC(&state->ref) > 0) {
+               // if not last reference
+               return;
+       }
+
+       // release connection reference on 1-->0 transition
+       if (state->svr) {
+               dispatch_sync(__nwi_configuration_queue(), ^{
+                       if (--nwi_active == 0) {
+                               // if last reference, drop connection
+                               libSC_info_client_release(nwi_client);
+                               nwi_client = NULL;
+                       }
+               });
        }
+
+       // release nwi_state
+       free(state);
+
        return;
 }
 
+static nwi_state *
+_nwi_state_copy_data()
+{
+       nwi_state_t             nwi_state       = NULL;
+       static const char       *proc_name      = NULL;
+       xpc_object_t            reqdict;
+       xpc_object_t            reply;
+
+       dispatch_sync(__nwi_configuration_queue(), ^{
+               if ((nwi_active++ == 0) || (nwi_client == NULL)) {
+                       static dispatch_once_t  once;
+                       static const char       *service_name   = NWI_SERVICE_NAME;
+
+                       dispatch_once(&once, ^{
+                               const char      *name;
+
+                               // get [XPC] service name
+                               name = getenv(service_name);
+                               if ((name != NULL) && (issetugid() == 0)) {
+                                       service_name = strdup(name);
+                               }
+
+                               // get process name
+                               proc_name = getprogname();
+                       });
+
+                       nwi_client =
+                               libSC_info_client_create(__nwi_configuration_queue(),   // dispatch queue
+                                                        service_name,                  // XPC service name
+                                                        "Network information");        // service description
+                       if (nwi_client == NULL) {
+                               --nwi_active;
+                       }
+               }
+       });
+
+       if ((nwi_client == NULL) || !nwi_client->active) {
+               // if network information server not available
+               return NULL;
+       }
+
+       // create message
+       reqdict = xpc_dictionary_create(NULL, NULL, 0);
+
+       // set process name
+       if (proc_name != NULL) {
+               xpc_dictionary_set_string(reqdict, NWI_PROC_NAME, proc_name);
+       }
+
+       // set request
+       xpc_dictionary_set_int64(reqdict, NWI_REQUEST, NWI_REQUEST_COPY);
+
+       // send request to the DNS configuration server
+       reply = libSC_send_message_with_reply_sync(nwi_client, reqdict);
+       xpc_release(reqdict);
+
+       if (reply != NULL) {
+               const void      *dataRef;
+               size_t          dataLen = 0;
+
+               dataRef = xpc_dictionary_get_data(reply, NWI_CONFIGURATION, &dataLen);
+               if (dataRef != NULL) {
+                       nwi_state = malloc(dataLen);
+                       bcopy((void *)dataRef, nwi_state, dataLen);
+                       nwi_state->ref = 0;
+                       nwi_state->svr = TRUE;
+               }
+
+               xpc_release(reply);
+       }
+
+       return nwi_state;
+}
+
 /*
  * Function: nwi_state_copy
  * Purpose:
@@ -141,12 +272,15 @@ nwi_state_release(nwi_state_t state)
 nwi_state_t
 nwi_state_copy(void)
 {
+       boolean_t       force_refresh;
        nwi_state_t     nwi_state = NULL;
        nwi_state_t     old_state = NULL;
 
        pthread_once(&initialized, _nwi_state_initialize);
        pthread_mutex_lock(&nwi_store_lock);
 
+       force_refresh = ATOMIC_CMPXCHG(&nwi_store_force_refresh, TRUE, FALSE);
+
        if (G_nwi_state != NULL) {
                int             check = 0;
                uint32_t        status;
@@ -164,7 +298,7 @@ nwi_state_copy(void)
                                check = 1;
                        }
                }
-               if (check != 0) {
+               if (check != 0 || force_refresh) {
                        /* new need snapshot */
                        old_state = G_nwi_state;
                        G_nwi_state = NULL;
@@ -172,7 +306,7 @@ nwi_state_copy(void)
        }
        /* Let's populate the cache if it's empty */
        if (G_nwi_state == NULL) {
-               G_nwi_state = _nwi_state_copy();
+               G_nwi_state = _nwi_state_copy_data();
                if (G_nwi_state != NULL) {
                        /* one reference for G_nwi_state */
                        nwi_state_retain(G_nwi_state);
@@ -202,6 +336,34 @@ nwi_state_copy(void)
 void
 _nwi_state_ack(nwi_state_t state, const char *bundle_id)
 {
+       xpc_object_t    reqdict;
+
+       if (state == NULL) {
+               return; // ASSERT
+       }
+
+       if ((nwi_client == NULL) || !nwi_client->active) {
+               // if network information server not available
+               return;
+       }
+
+       dispatch_sync(__nwi_configuration_queue(), ^{
+               nwi_active++;   // keep connection active (for the life of the process)
+       });
+
+       // create message
+       reqdict = xpc_dictionary_create(NULL, NULL, 0);
+
+       // set request
+       xpc_dictionary_set_int64(reqdict, NWI_REQUEST, NWI_REQUEST_ACKNOWLEDGE);
+
+       // set generation
+       xpc_dictionary_set_uint64(reqdict, NWI_GENERATION, state->generation_count);
+
+       // send acknowledgement to the DNS configuration server
+       xpc_connection_send_message(nwi_client->connection, reqdict);
+
+       xpc_release(reqdict);
        return;
 }
 
@@ -218,6 +380,17 @@ nwi_state_get_generation(nwi_state_t state)
        return (state->generation_count);
 }
 
+/*
+ * Function: nwi_ifstate_get_generation
+ * Purpose:
+ *   Returns the generation (mach_time) of the nwi_ifstate data.
+ */
+uint64_t
+nwi_ifstate_get_generation(nwi_ifstate_t ifstate)
+{
+       return (ifstate->if_generation_count);
+}
+
 /*
  * Function: nwi_ifstate_get_ifname
  * Purpose:
@@ -370,3 +543,238 @@ nwi_ifstate_compare_rank(nwi_ifstate_t ifstate1, nwi_ifstate_t ifstate2)
 {
        return RankCompare(ifstate1->rank, ifstate2->rank);
 }
+
+/*
+ * nwi_state_get_reachability_flags
+ *
+ * returns the global reachability flags for a given address family.
+ * If no address family is passed in, it returns the global reachability
+ * flags for either families.
+ *
+ * The reachability flags returned follow the definition of
+ * SCNetworkReachabilityFlags.
+ *
+ * If the flags are zero (i.e. do not contain kSCNetworkReachabilityFlagsReachable), there is no connectivity.
+ *
+ * Otherwise, at least kSCNetworkReachabilityFlagsReachable is set:
+ *        Reachable only
+ *          No other connection flags are set.
+ *        Reachable and no ConnectionRequired
+ *          If we have connectivity for the specified address family (and we'd
+ *          be returning the reachability flags associated with the default route)
+ *        Reachable and ConnectionRequired
+ *          If we do not currently have an active/primary network but we may
+ *          be able to establish connectivity.
+ *        Reachable and OnDemand
+ *          If we do not currently have an active/primary network but we may
+ *          be able to establish connective on demand.
+ *        Reachable and TransientConnection
+ *          This connection is transient.
+ *        Reachable and WWAN
+ *          This connection will be going over the cellular network.
+ */
+uint32_t
+nwi_state_get_reachability_flags(nwi_state_t nwi_state, int af)
+{
+       if (nwi_state == NULL) {
+               return (0);
+       }
+       if (af == AF_INET || af == AF_INET6) {
+               nwi_ifstate_t ifstate;
+
+               ifstate = nwi_state_get_first_ifstate(nwi_state, af);
+
+               if (ifstate != NULL) {
+                       return ifstate->reach_flags;
+               }
+
+               return (af == AF_INET) ? nwi_state->reach_flags_v4 : nwi_state->reach_flags_v6;
+       } else {
+               nwi_ifstate_t ifstate_v4;
+               nwi_ifstate_t ifstate_v6;
+
+               ifstate_v4 = nwi_state_get_first_ifstate(nwi_state, AF_INET);
+               ifstate_v6 = nwi_state_get_first_ifstate(nwi_state, AF_INET6);
+
+               if (ifstate_v4 != NULL) {
+                       if (ifstate_v6 != NULL) {
+                               if (nwi_ifstate_compare_rank(ifstate_v4, ifstate_v6) > 0) {
+                                       return ifstate_v6->reach_flags;
+                               } else {
+                                       return ifstate_v4->reach_flags;
+                               }
+                       } else {
+                               return ifstate_v4->reach_flags;
+                       }
+               } else {
+                       if (ifstate_v6 != NULL) {
+                               return ifstate_v6->reach_flags;
+                       }
+               }
+
+               if (nwi_state->reach_flags_v4 != 0) {
+                       return nwi_state->reach_flags_v4;
+               }
+               // This is the case where both ifstate are NULL.
+               return nwi_state->reach_flags_v6;
+       }
+}
+
+/*
+ * nwi_ifstate_get_vpn_server
+ *
+ * returns a sockaddr representation of the vpn server address.
+ * NULL if PPP/VPN/IPSec server address does not exist.
+ */
+const struct sockaddr *
+nwi_ifstate_get_vpn_server(nwi_ifstate_t ifstate)
+{
+       const struct sockaddr * vpn_server_addr;
+
+       vpn_server_addr = (const struct sockaddr *)(void *)
+                          &ifstate->vpn_server_address;
+
+       if (vpn_server_addr->sa_family == 0) {
+               return NULL;
+       }
+       return vpn_server_addr;
+}
+
+/*
+ * nwi_ifstate_get_reachability_flags
+ *
+ * returns the reachability flags for the interface given an address family.
+ * The flags returned are those determined outside of
+ * the routing table.  [None, ConnectionRequired, OnDemand,
+ * Transient Connection, WWAN].
+ */
+uint32_t
+nwi_ifstate_get_reachability_flags(nwi_ifstate_t ifstate)
+{
+       return ifstate->reach_flags;
+}
+
+/*
+ * nwi_ifstate_get_signature
+ *
+ * returns the signature and its length for an ifstate given an address family.
+ * If AF_UNSPEC is passed in, the signature for a given ifstate is returned.
+ *
+ * If the signature does not exist, NULL is returned.
+ */
+const uint8_t *
+nwi_ifstate_get_signature(nwi_ifstate_t ifstate, int af, int * length)
+{
+       nwi_ifstate_t i_state = NULL;
+
+       switch (af) {
+               case AF_UNSPEC:
+                       i_state = ifstate;
+                       break;
+               case AF_INET:
+               case AF_INET6:
+                       i_state = (ifstate->af == af) ? ifstate : ifstate->af_alias;
+                       break;
+               default:
+                       break;
+
+       }
+
+       if (i_state != NULL) {
+               if ((i_state->flags & NWI_IFSTATE_FLAGS_HAS_SIGNATURE) != 0) {
+                       *length = sizeof(i_state->signature);
+                       return (i_state->signature);
+               }
+       }
+
+       *length = 0;
+       return NULL;
+}
+
+static inline
+boolean_t
+_nwi_ifstate_is_in_list(nwi_ifstate_t ifstate, int af)
+{
+       nwi_ifstate_t i_state;
+
+       i_state = (ifstate->af == af) ? ifstate : ifstate->af_alias;
+       if (i_state == NULL) {
+               return FALSE;
+       }
+
+       if ((nwi_ifstate_get_flags(i_state) & NWI_IFSTATE_FLAGS_NOT_IN_LIST) == 0) {
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+/*
+ * nwi_ifstate_get_dns_signature
+ *
+ * returns the signature and its length for given
+ * ifstate with a valid dns configuration.
+ *
+ * If the signature does not exist, NULL is returned.
+ *
+ */
+const uint8_t *
+nwi_ifstate_get_dns_signature(nwi_ifstate_t ifstate, int * length)
+{
+       const uint8_t * signature = NULL;
+       const uint8_t * v4_signature;
+       int             v4_signature_len;
+       const uint8_t * v6_signature;
+       int             v6_signature_len;
+
+       *length = 0;
+
+       if ((nwi_ifstate_get_flags(ifstate) & NWI_IFSTATE_FLAGS_HAS_DNS) == 0) {
+               return NULL;
+       }
+
+       v4_signature = nwi_ifstate_get_signature(ifstate, AF_INET, &v4_signature_len);
+       v6_signature = nwi_ifstate_get_signature(ifstate, AF_INET6, &v6_signature_len);
+       if (v4_signature == NULL && v6_signature == NULL) {
+               return NULL;
+       }
+
+       if (_nwi_ifstate_is_in_list(ifstate, AF_INET) == TRUE) {
+               signature = v4_signature;
+               *length = v4_signature_len;
+       } else {
+               if (_nwi_ifstate_is_in_list(ifstate, AF_INET6) != TRUE && v4_signature_len > 0) {
+                       /* v6 is ranked never, v4 is ranked never but has a valid signature */
+                       signature = v4_signature;
+                       *length = v4_signature_len;
+               } else {
+                       /* v6 is not ranked never or v4 has no signature */
+                       signature = v6_signature;
+                       *length = v6_signature_len;
+               }
+       }
+
+       return signature;
+}
+
+
+#pragma mark -
+#pragma mark Network information [nwi] test code
+
+
+#ifdef MAIN
+
+int
+main(int argc, char **argv)
+{
+       dns_config_t    *config;
+
+       config = dns_configuration_copy();
+       if (config != NULL) {
+               dns_configuration_free(&config);
+       }
+
+       exit(0);
+}
+
+#endif
index 418b304498297a4f947edcc96937213187f28546..7c364fcd29694ef83c1deb2ba10112a769b032fa 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2011-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #define _NETWORK_INFORMATION_H_
 
 #include <stdint.h>
+#include <sys/cdefs.h>
 
 typedef struct _nwi_state * nwi_state_t;
 typedef struct _nwi_ifstate * nwi_ifstate_t;
 
+__BEGIN_DECLS
+
 /*
  * Function: nwi_state_copy
  * Purpose:
@@ -81,13 +84,21 @@ nwi_state_get_first_ifstate(nwi_state_t state, int af);
 /*
  * Function: nwi_state_get_generation
  * Purpose:
- *   Returns the generation (mach_time) of the nwi_state data.
+ *   Returns the generation of the nwi_state data.
  *   Every time the data is updated due to changes
  *   in the network, this value will change.
  */
 uint64_t
 nwi_state_get_generation(nwi_state_t state);
 
+/*
+ * Function: nwi_ifstate_get_generation
+ * Purpose:
+ *   Returns the generation of the nwi_ifstate data.
+ */
+uint64_t
+nwi_ifstate_get_generation(nwi_ifstate_t ifstate);
+
 /*
  * Function: nwi_state_get_ifstate
  * Purpose:
@@ -165,4 +176,82 @@ void
 _nwi_state_ack(nwi_state_t state, const char *bundle_id)
        __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_6_0);
 
+/*
+ * nwi_state_get_reachability_flags
+ *
+ * returns the global reachability flags for a given address family.
+ * If no address family is passed in, it returns the global reachability
+ * flags for either families.
+ *
+ * The reachability flags returned follow the definition of
+ * SCNetworkReachabilityFlags.
+ *
+ * If the flags are zero (i.e. do not contain kSCNetworkReachabilityFlagsReachable), there is no connectivity.
+ *
+ * Otherwise, at least kSCNetworkReachabilityFlagsReachable is set:
+ *        Reachable only
+ *          No other connection flags are set.
+ *        Reachable and no ConnectionRequired
+ *          If we have connectivity for the specified address family (and we'd
+ *          be returning the reachability flags associated with the default route)
+ *        Reachable and ConnectionRequired
+ *          If we do not currently have an active/primary network but we may
+ *          be able to establish connectivity.
+ *        Reachable and OnDemand
+ *          If we do not currently have an active/primary network but we may
+ *          be able to establish connective on demand.
+ *        Reachable and TransientConnection
+ *          This connection is transient.
+ *        Reachable and WWAN
+ *          This connection will be going over the cellular network.
+ */
+uint32_t
+nwi_state_get_reachability_flags(nwi_state_t nwi_state, int af);
+
+/*
+ * nwi_ifstate_get_vpn_server
+ *
+ * returns a sockaddr representation of the vpn server address.
+ * NULL if PPP/VPN/IPSec server address does not exist.
+ */
+const struct sockaddr *
+nwi_ifstate_get_vpn_server(nwi_ifstate_t ifstate);
+
+/*
+ * nwi_ifstate_get_reachability_flags
+ *
+ * returns the reachability flags for the interface given an address family.
+ * The flags returned are those determined outside of
+ * the routing table.  [None, ConnectionRequired, OnDemand,
+ * Transient Connection, WWAN].
+ */
+uint32_t
+nwi_ifstate_get_reachability_flags(nwi_ifstate_t ifstate);
+
+/*
+ * nwi_ifstate_get_signature
+ *
+ * returns the signature and its length for an ifstate given an address family.
+ * If AF_UNSPEC is passed in, the signature for a given ifstate is returned.
+ *
+ * If the signature does not exist, NULL is returned.
+ */
+const uint8_t *
+nwi_ifstate_get_signature(nwi_ifstate_t ifstate, int af, int * length);
+
+
+/*
+ * nwi_ifstate_get_dns_signature
+ *
+ * returns the signature and its length for given
+ * ifstate with a valid dns configuration.
+ *
+ * If the signature does not exist, NULL is returned.
+ *
+ */
+const uint8_t *
+nwi_ifstate_get_dns_signature(nwi_ifstate_t ifstate, int * length);
+
+__END_DECLS
+
 #endif
index 7dfc706bdd35d7a4b60c646305e69371fbd8f3f7..af1f1ba177020de64143481a6045134099234568 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2011-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  */
 
 #include <arpa/inet.h>
+#include <assert.h>
 #include <notify.h>
 #include <string.h>
 #include <sys/socket.h>
 #include <stdlib.h>
-#include <syslog.h>
 #include <stdbool.h>
 #include "network_information_priv.h"
 #include <limits.h>
+#include <stdio.h>
 
-sa_family_t nwi_af_list[] = {AF_INET, AF_INET6};
+__private_extern__
+const sa_family_t nwi_af_list[] = {AF_INET, AF_INET6};
 
 static __inline__ unsigned int
 nwi_state_compute_size(unsigned int n)
@@ -55,6 +57,7 @@ nwi_state_copy_priv(nwi_state_t src)
                bcopy(src, dest, src->size);
 
                dest->ref = 1;
+               dest->svr = FALSE;
        }
        return dest;
 }
@@ -86,6 +89,7 @@ nwi_state_new(nwi_state_t old_state, int elems)
                return NULL;
        }
 
+       bzero(state, new_size);
        state->size = new_size;
 
        /*
@@ -103,7 +107,6 @@ nwi_state_new(nwi_state_t old_state, int elems)
                }
 
                state->ipv4_count = old_state->ipv4_count;
-
                if (state->ipv4_count > 0) {
                        bcopy((void*) old_state->nwi_ifstates,
                              (void*) state->nwi_ifstates,
@@ -119,33 +122,47 @@ nwi_state_new(nwi_state_t old_state, int elems)
        nwi_state_set_last(state, AF_INET6);
 
        state->ref = 1;
+       state->svr = FALSE;
        return state;
 }
 
-static inline
-nwi_ifstate_t nwi_ifstate_get_last(nwi_state_t state, int af, uint32_t** last)
+static __inline__
+nwi_ifstate_t
+nwi_ifstate_get_last(nwi_state_t state, int af, uint32_t** last)
 {
        uint32_t*       count;
        int             idx;
 
-       count = (af == AF_INET)
-               ?&state->ipv4_count:&state->ipv6_count;
+       assert(state != NULL);
+
+       count = (af == AF_INET) ? &state->ipv4_count
+                               : &state->ipv6_count;
 
-       idx = (af == AF_INET)
-               ?state->ipv4_count:(state->ipv6_start + state->ipv6_count);
+       idx = (af == AF_INET) ? state->ipv4_count
+                             : (state->ipv6_start + state->ipv6_count);
 
        *last = count;
 
        return &state->nwi_ifstates[idx];
-
 }
 
 __private_extern__
 void
+nwi_ifstate_set_signature(nwi_ifstate_t ifstate, uint8_t * signature)
+{
+       bcopy(signature, ifstate->signature, sizeof(ifstate->signature));
+       ifstate->flags |= NWI_IFSTATE_FLAGS_HAS_SIGNATURE;
+       return;
+}
+
+__private_extern__
+nwi_ifstate_t
 nwi_insert_ifstate(nwi_state_t state,
-                  const char* ifname, int af,
+                  const char * ifname, int af,
                   uint64_t flags, Rank rank,
-                  void* ifa)
+                  void * ifa,
+                  struct sockaddr * vpn_server_addr,
+                  uint32_t reach_flags)
 {
        nwi_ifstate_t   ifstate;
 
@@ -155,7 +172,7 @@ nwi_insert_ifstate(nwi_state_t state,
        /* Already present, just ignore it */
        if (ifstate != NULL) {
                if (ifstate->rank < rank) {
-                       return;
+                       return NULL;
                }
        }
 
@@ -164,10 +181,9 @@ nwi_insert_ifstate(nwi_state_t state,
 
                /* We need to append it as the last element */
                ifstate = nwi_ifstate_get_last(state, af, &last);
-               strcpy(ifstate->ifname, ifname);
-               ifstate->af_alias = NULL;
+               bzero(ifstate, sizeof(*ifstate));
+               strlcpy(ifstate->ifname, ifname, sizeof(ifstate->ifname));
                ifstate->af = af;
-               ifstate->diff_ch = NULL;
                (*last)++;
        }
 
@@ -187,10 +203,17 @@ nwi_insert_ifstate(nwi_state_t state,
 
        }
 
+       if (vpn_server_addr != NULL && vpn_server_addr->sa_family != 0) {
+               _nwi_ifstate_set_vpn_server(ifstate, vpn_server_addr);
+       } else {
+               _nwi_ifstate_set_vpn_server(ifstate, NULL);
+       }
+
+       ifstate->reach_flags = reach_flags;
        ifstate->rank = rank;
        ifstate->flags = flags;
 
-       return;
+       return ifstate;
 }
 
 __private_extern__
@@ -220,79 +243,18 @@ nwi_state_set_last(nwi_state_t state, int af)
 
        /* The last element is an element with the flags set as
         * NWI_IFSTATE_FLAGS_NOT_IN_LIST */
-       last_elem_idx = (af == AF_INET)
-                       ?state->ipv4_count
-                       :(state->ipv6_start + state->ipv6_count);
+       last_elem_idx = (af == AF_INET) ? state->ipv4_count
+                                       : (state->ipv6_start + state->ipv6_count);
 
        state->nwi_ifstates[last_elem_idx].ifname[0] = '\0';
-       state->nwi_ifstates[last_elem_idx].flags
-           |= NWI_IFSTATE_FLAGS_NOT_IN_LIST;
+       state->nwi_ifstates[last_elem_idx].flags = NWI_IFSTATE_FLAGS_NOT_IN_LIST;
 }
 
-__private_extern__
-void
-_nwi_state_dump(int level, nwi_state_t state)
-{
-       const char *            addr_str;
-       void *                  address;
-       int                     i;
-       char                    ntopbuf[INET6_ADDRSTRLEN];
-       nwi_ifstate_t           scan;
-
-
-       if (state == NULL) {
-               syslog(level, "<empty nwi_state>");
-               return;
-       }
-       syslog(level, "nwi_state = { gen = %llu size = %u #ipv4 = %u #ipv6 = %u }",
-              state->generation_count,
-              state->size,
-              state->ipv4_count,
-              state->ipv6_count);
-
-       if (state->ipv4_count) {
-               syslog(level, "IPv4:");
-               for (i = 0, scan = state->nwi_ifstates;
-                    i < state->ipv4_count; i++, scan++) {
-                       bool has_dns = (scan->flags & NWI_IFSTATE_FLAGS_HAS_DNS) != 0;
-                       bool never = (scan->flags & NWI_IFSTATE_FLAGS_NOT_IN_LIST) != 0;
-
-                       address = nwi_ifstate_get_address(scan);
-                       addr_str =  inet_ntop(scan->af, address, ntopbuf, sizeof(ntopbuf));
-
-                       syslog(level, "    [%d]: %s%s%s%s rank %u iaddr: %s " ,
-                              i, scan->ifname, scan->diff_ch != NULL?scan->diff_ch:"",
-                              has_dns ? " dns" : "",
-                              never ? " never" : "",
-                              scan->rank,
-                              addr_str);
-               }
-       }
-       if (state->ipv6_count) {
-               syslog(level, "IPv6:");
-               for (i = 0, scan = state->nwi_ifstates + state->ipv6_start;
-                    i < state->ipv6_count; i++, scan++) {
-                       bool has_dns = (scan->flags & NWI_IFSTATE_FLAGS_HAS_DNS) != 0;
-                       bool never = (scan->flags & NWI_IFSTATE_FLAGS_NOT_IN_LIST) != 0;
-
-                       address = nwi_ifstate_get_address(scan);
-                       addr_str =  inet_ntop(scan->af, address, ntopbuf, sizeof(ntopbuf));
-                       syslog(level, "    [%d]: %s%s%s%s rank %u iaddr6: %s ",
-                              i, scan->ifname, scan->diff_ch != NULL?scan->diff_ch:"",
-                              has_dns ? " dns" : "",
-                              never ? " never" : "",
-                              scan->rank,
-                              addr_str);
-               }
-       }
-       return;
-}
-
-
 #define        unchanged       ""
 #define added          "+"
 #define deleted                "-"
 #define changed                "!"
+#define rank_change    "R"
 
 __private_extern__
 void *
@@ -305,7 +267,10 @@ __private_extern__
 const char *
 nwi_ifstate_get_diff_str(nwi_ifstate_t ifstate)
 {
-       return ifstate->diff_ch;
+       if (strcmp(ifstate->diff_str, rank_change) == 0) {
+               return changed;
+       }
+       return ifstate->diff_str;
 }
 
 static
@@ -313,10 +278,6 @@ inline
 boolean_t
 nwi_ifstate_has_changed(nwi_ifstate_t ifstate1, nwi_ifstate_t ifstate2)
 {
-       if (ifstate1->rank != ifstate2->rank) {
-               return TRUE;
-       }
-
        if (ifstate1->flags != ifstate2->flags) {
                return TRUE;
        }
@@ -350,85 +311,116 @@ nwi_ifstate_append(nwi_state_t state, nwi_ifstate_t scan)
 static
 inline
 void
-nwi_ifstate_set_diff_str(nwi_ifstate_t ifstate, const char * ch)
+nwi_ifstate_set_diff_str(nwi_ifstate_t ifstate, const char *diff_str)
 {
-       ifstate->diff_ch = ch;
+       ifstate->diff_str = diff_str;
 }
 
 static
 void
-nwi_state_merge_added(nwi_state_t state, nwi_state_t old_state,
-                   nwi_state_t new_state)
+nwi_ifstate_set_added_or_changed_str(nwi_state_t state, nwi_state_t old_state, nwi_ifstate_t ifstate)
 {
-       int idx;
-       nwi_ifstate_t scan;
-
-       /* Iterate through v4 and v6 list and annotate the diff flags */
-       for (idx = 0; idx < sizeof(nwi_af_list)/sizeof(nwi_af_list[0]); idx++) {
-               scan = nwi_state_get_first_ifstate(new_state, nwi_af_list[idx]);
+       nwi_ifstate_t   existing_ifstate, new_ifstate;
+
+       existing_ifstate = nwi_state_get_ifstate_with_name(old_state,
+                                                          ifstate->af,
+                                                          nwi_ifstate_get_ifname(ifstate));
+
+       /* Add the element that is not in the store */
+       new_ifstate = nwi_ifstate_append(state, ifstate);
+
+       /* These are potentially "added" elements unless they are
+        * in the old list */
+       nwi_ifstate_set_diff_str(new_ifstate, added);
+
+       if (existing_ifstate != NULL) {
+               if (nwi_ifstate_has_changed(existing_ifstate, new_ifstate) == TRUE) {
+                       nwi_ifstate_set_diff_str(new_ifstate, changed);
+               } else if (existing_ifstate->rank != new_ifstate->rank) {
+                       nwi_ifstate_set_diff_str(new_ifstate, rank_change);
+               } else {
+                       nwi_ifstate_set_diff_str(new_ifstate, unchanged);
+               }
+       }
+       return;
+}
 
-               while (scan != NULL) {
-                       nwi_ifstate_t   existing_ifstate, new_ifstate;
-                       const char*     ifname;
+static
+void
+nwi_ifstate_set_removed_str(nwi_state_t state, nwi_ifstate_t ifstate)
+{
+       nwi_ifstate_t   existing_ifstate;
 
-                       ifname = nwi_ifstate_get_ifname(scan);
+       existing_ifstate = nwi_state_get_ifstate_with_name(state,
+                                                          ifstate->af,
+                                                          nwi_ifstate_get_ifname(ifstate));
 
-                       existing_ifstate = nwi_state_get_ifstate_with_name(old_state, scan->af, ifname);
+       /* Any elements that has not been added means that they are removed */
+       if (existing_ifstate == NULL) {
+               nwi_ifstate_t new_ifstate = nwi_ifstate_append(state, ifstate);
+               nwi_ifstate_set_diff_str(new_ifstate, deleted);
+       }
+       return;
+}
 
-                       /* Add the element that is not in the store */
-                       new_ifstate = nwi_ifstate_append(state, scan);
+static
+void
+nwi_state_merge_added(nwi_state_t state, nwi_state_t old_state,
+                   nwi_state_t new_state)
+{
+       int i;
+       nwi_ifstate_t scan;
 
-                       /* These are potentially "added" elements unless they are
-                        * in the old list */
-                       nwi_ifstate_set_diff_str(new_ifstate, added);
+       if (new_state == NULL) {
+               return;
+       }
 
-                       if (existing_ifstate != NULL) {
-                               if (nwi_ifstate_has_changed(existing_ifstate, new_ifstate) == TRUE) {
-                                       nwi_ifstate_set_diff_str(new_ifstate, changed);
-                               } else {
-                                       nwi_ifstate_set_diff_str(new_ifstate, unchanged);
-                               }
-                       }
-                       scan = nwi_ifstate_get_next(scan, scan->af);
+       if (new_state->ipv4_count) {
+               for (i = 0, scan = new_state->nwi_ifstates;
+                    i < new_state->ipv4_count; i++, scan++) {
+                       nwi_ifstate_set_added_or_changed_str(state, old_state, scan);
                }
-               nwi_state_set_last(state, nwi_af_list[idx]);
+               nwi_state_set_last(state, AF_INET);
        }
 
+       if (new_state->ipv6_count) {
+               for (i = 0, scan = new_state->nwi_ifstates + new_state->ipv6_start;
+                    i < new_state->ipv6_count; i++, scan++) {
+                       nwi_ifstate_set_added_or_changed_str(state, old_state, scan);
+               }
+               nwi_state_set_last(state, AF_INET6);
+       }
        return;
 }
 
-static
 void
 nwi_state_merge_removed(nwi_state_t state, nwi_state_t old_state)
 {
-       int idx;
+       int i;
        nwi_ifstate_t scan;
 
-       /* Iterate through v4 and v6 list and annotate the diff flags */
-       for (idx = 0; idx < sizeof(nwi_af_list)/sizeof(nwi_af_list[0]); idx++) {
-               scan = nwi_state_get_first_ifstate(old_state, nwi_af_list[idx]);
-
-               while (scan != NULL) {
-                       nwi_ifstate_t   existing_ifstate;
-                       const char*     ifname;
-
-                       ifname = nwi_ifstate_get_ifname(scan);
-
-                       existing_ifstate = nwi_state_get_ifstate_with_name(state, scan->af, ifname);
+       if (old_state == NULL) {
+               return;
+       }
 
-                       /* Any elements that has not been added means that they are removed */
-                       if (existing_ifstate == NULL) {
-                               nwi_ifstate_t new_ifstate = nwi_ifstate_append(state, scan);
-                               nwi_ifstate_set_diff_str(new_ifstate, deleted);
-                       }
-                       scan = nwi_ifstate_get_next(scan, scan->af);
+       if (old_state->ipv4_count) {
+               for (i = 0, scan = old_state->nwi_ifstates;
+                    i < old_state->ipv4_count; i++, scan++) {
+                       nwi_ifstate_set_removed_str(state, scan);
                }
-               nwi_state_set_last(state, nwi_af_list[idx]);
+               nwi_state_set_last(state, AF_INET);
        }
 
+       if (old_state->ipv6_count) {
+               for (i = 0, scan = old_state->nwi_ifstates + old_state->ipv6_start;
+                    i < old_state->ipv6_count; i++, scan++) {
+                       nwi_ifstate_set_removed_str(state, scan);
+               }
+               nwi_state_set_last(state, AF_INET6);
+       }
+       return;
 }
 
-
 __private_extern__
 nwi_state_t
 nwi_state_diff(nwi_state_t old_state, nwi_state_t new_state)
@@ -453,7 +445,111 @@ nwi_state_diff(nwi_state_t old_state, nwi_state_t new_state)
        nwi_state_merge_added(diff, old_state,  new_state);
        nwi_state_merge_removed(diff, old_state);
 
-       /* Diff consists of a nwi_state_t with annotated diff_ch's */
+       /* Diff consists of a nwi_state_t with annotated diff_str's */
        return diff;
 }
 
+static __inline__
+void
+_nwi_ifstate_set_generation(nwi_ifstate_t ifstate, uint64_t generation_count)
+{
+       ifstate->if_generation_count = generation_count;
+
+       return;
+}
+
+static
+boolean_t
+_nwi_ifstate_has_changed(nwi_state_t state, const char * ifname)
+{
+       nwi_ifstate_t   ifstate;
+
+       /* If either the v4 ifstate or the v6 ifstate
+        * has changed, then report that the interface has changed */
+       ifstate = nwi_state_get_ifstate_with_name(state,
+                                                 AF_INET,
+                                                 ifname);
+
+       if (ifstate != NULL
+           && ifstate->diff_str != NULL
+           && strcmp(ifstate->diff_str, unchanged) != 0
+           && strcmp(ifstate->diff_str, rank_change) != 0) {
+               return (TRUE);
+       }
+
+       ifstate = nwi_state_get_ifstate_with_name(state,
+                                                 AF_INET6,
+                                                 ifname);
+
+       if (ifstate != NULL
+           && ifstate->diff_str != NULL
+           && strcmp(ifstate->diff_str, unchanged) != 0
+           && strcmp(ifstate->diff_str, rank_change) != 0) {
+               return (TRUE);
+       }
+       return (FALSE);
+}
+
+__private_extern__
+void
+_nwi_state_update_interface_generations(nwi_state_t old_state, nwi_state_t state, nwi_state_t changes)
+{
+       int             i;
+       uint64_t        generation_count;
+       nwi_ifstate_t   scan;
+
+       if (state == NULL || changes == NULL) {
+               return;
+       }
+
+       /* cache the generation count */
+       generation_count = state->generation_count;
+
+       if (state->ipv4_count) {
+               for (i = 0, scan = state->nwi_ifstates;
+                    i < state->ipv4_count; i++, scan++) {
+                       if (_nwi_ifstate_has_changed(changes, scan->ifname) == TRUE) {
+                               /* Update the interface generation count */
+                               _nwi_ifstate_set_generation(scan, generation_count);
+                       } else {
+                               nwi_ifstate_t old_ifstate;
+
+                               old_ifstate = nwi_state_get_ifstate_with_name(old_state,
+                                                                             AF_INET,
+                                                                             scan->ifname);
+
+                               /* Set the current generation count */
+                               _nwi_ifstate_set_generation(scan,
+                                                           old_ifstate->if_generation_count);
+                       }
+               }
+       }
+
+       if (state->ipv6_count) {
+               for (i = 0, scan = state->nwi_ifstates + state->ipv6_start;
+                    i < state->ipv6_count; i++, scan++) {
+                       /* The generation count has been already updated in
+                        * the ipv4 case, just skip it. */
+                       if (nwi_ifstate_get_generation(scan) ==
+                               generation_count) {
+                               continue;
+                       }
+                       if (_nwi_ifstate_has_changed(changes, scan->ifname) == TRUE) {
+                               /* update the interface generation count */
+                               _nwi_ifstate_set_generation(scan, generation_count);
+                       } else {
+                               nwi_ifstate_t old_ifstate;
+
+                               old_ifstate = nwi_state_get_ifstate_with_name(old_state,
+                                                                             AF_INET6,
+                                                                             scan->ifname);
+                               assert(old_ifstate != NULL);
+
+                               /* Set the current generation count */
+                               _nwi_ifstate_set_generation(scan,
+                                                           old_ifstate->if_generation_count);
+                       }
+               }
+       }
+       return;
+}
index 3eb3c12c1ba70bc699ab873f142301c01ebeeda0..5ea1ded7e3c61abf38f2deac5341085958d7ba71 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2011-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -24,7 +24,9 @@
 #ifndef _NETWORK_INFORMATION_PRIV_H_
 #define _NETWORK_INFORMATION_PRIV_H_
 
+#include <CommonCrypto/CommonDigest.h>
 #include <net/if.h>
+#include <stdbool.h>
 #include <stdint.h>
 #include <string.h>
 #include <netinet/in.h>
 
 #include "network_information.h"
 
-__private_extern__
-sa_family_t nwi_af_list[2];
+extern const sa_family_t nwi_af_list[2];
 
 #define NWI_IFSTATE_FLAGS_NOT_IN_LIST  0x8
+#define NWI_IFSTATE_FLAGS_HAS_SIGNATURE        0x10
+
+#define        NWI_PTR(type, name)                             \
+       union {                                         \
+               type            name;                   \
+               uint64_t        _ ## name ## _p;        \
+       }
 
 typedef uint32_t        Rank;
 
+#pragma pack(4)
 typedef struct _nwi_ifstate {
-       char ifname[IFNAMSIZ];
-       uint64_t flags;
-       nwi_ifstate_t af_alias;
-       Rank rank;
-       int af;
+       char                    ifname[IFNAMSIZ];
+       uint64_t                flags;
+       NWI_PTR(nwi_ifstate_t,  af_alias);
+       Rank                    rank;
+       sa_family_t             af;
        union {
-               struct in_addr iaddr;
-               struct in6_addr iaddr6;
+           struct in_addr      iaddr;
+           struct in6_addr     iaddr6;
        };
-       const char* diff_ch;
+       NWI_PTR(const char *,   diff_str);
+       uint64_t                if_generation_count;
+       uint32_t                reach_flags;
+       union {
+           struct sockaddr_in  vpn_server_address4;
+           struct sockaddr_in6 vpn_server_address6;
+       } vpn_server_address;
+       unsigned char           signature[CC_SHA1_DIGEST_LENGTH];
 } nwi_ifstate;
+#pragma pack()
 
 /*
  * nwi_state
@@ -71,7 +88,16 @@ typedef struct _nwi_ifstate {
  *| ipv6_start                                  |-------+
  *|                                             |       |
  *|---------------------------------------------+       |ipv6_start stores the index of the start of the v6 list.
- *| ref                                         |       |
+ *| ref (reference count)                       |       |
+ *|                                             |       |
+ *|---------------------------------------------+       |
+ *| svr (TRUE if copied from server)            |       |
+ *|                                             |       |
+ *|---------------------------------------------+       |
+ *| reach_flags_v4                              |       |
+ *|                                             |       |
+ *|---------------------------------------------+       |
+ *| reach_flags_v6                              |       |
  *|                                             |       |
  *|---------------------------------------------+       |
  *| IPv4 nwi_ifstates                           |       |
@@ -92,21 +118,26 @@ typedef struct _nwi_ifstate {
  *|---------------------------------------------+
  *
  */
+#pragma pack(4)
 typedef struct _nwi_state {
-       uint64_t generation_count;
-       uint32_t size;
-       uint32_t ipv4_count;
-       uint32_t ipv6_count;
-       uint32_t ipv6_start;
-       uint32_t ref;
-       nwi_ifstate nwi_ifstates[0];
+       uint64_t        generation_count;
+       uint32_t        size;
+       uint32_t        ipv4_count;
+       uint32_t        ipv6_count;
+       uint32_t        ipv6_start;
+       uint32_t        ref;
+       _Bool           svr;
+       uint32_t        reach_flags_v4;
+       uint32_t        reach_flags_v6;
+       nwi_ifstate     nwi_ifstates[0];
 } nwi_state;
+#pragma pack()
 
 static __inline__ int
 uint32_cmp(uint32_t a, uint32_t b)
 {
        int             ret;
-       
+
        if (a == b) {
                ret = 0;
        }
@@ -203,50 +234,73 @@ nwi_state_get_ifstate_with_name(nwi_state_t state,
        return (NULL);
 }
 
-__private_extern__
+static __inline__
+void
+_nwi_ifstate_set_vpn_server(nwi_ifstate_t ifstate, struct sockaddr *serv_addr)
+{
+       size_t len;
+
+       if (serv_addr == NULL) {
+               bzero(&ifstate->vpn_server_address,
+                     sizeof(ifstate->vpn_server_address));
+               return;
+       }
+
+       len = serv_addr->sa_len;
+
+       if (len == 0 || len > sizeof(ifstate->vpn_server_address)) {
+               return;
+       }
+
+       memcpy(&ifstate->vpn_server_address,
+              serv_addr,
+              len);
+       return;
+
+}
+
+static __inline__
+void
+_nwi_state_set_reachability_flags(nwi_state_t state, uint32_t reach_flags_v4, uint32_t reach_flags_v6)
+{
+       state->reach_flags_v4 = reach_flags_v4;
+       state->reach_flags_v6 = reach_flags_v6;
+       return;
+}
+
 nwi_state_t
 nwi_state_new(nwi_state_t old_state, int elems);
 
-__private_extern__
 nwi_state_t
 nwi_state_copy_priv(nwi_state_t old_state);
 
-__private_extern__
-void
+nwi_ifstate_t
 nwi_insert_ifstate(nwi_state_t state, const char* ifname, int af,
                   uint64_t flags, Rank rank,
-                  void * ifa);
+                  void * ifa, struct sockaddr * vpn_server_addr, uint32_t reach_flags);
+
+void
+nwi_ifstate_set_signature(nwi_ifstate_t ifstate, uint8_t * signature);
 
-__private_extern__
 void
 nwi_state_clear(nwi_state_t state, int af);
 
-__private_extern__
 void
 nwi_state_set_last(nwi_state_t state, int af);
 
-__private_extern__
 nwi_state_t
 nwi_state_diff(nwi_state_t old_state, nwi_state_t new_state);
 
-__private_extern__
 void *
 nwi_ifstate_get_address(nwi_ifstate_t ifstate);
 
-__private_extern__
 const char *
 nwi_ifstate_get_diff_str(nwi_ifstate_t ifstate);
 
-__private_extern__
-_Bool
-_nwi_state_store(nwi_state_t state);
-
-__private_extern__
-nwi_state_t
-_nwi_state_copy(void);
+void
+_nwi_state_update_interface_generations(nwi_state_t old_state, nwi_state_t state, nwi_state_t changes);
 
-__private_extern__
 void
-_nwi_state_dump(int level, nwi_state_t state);
+_nwi_state_force_refresh();
 
 #endif
diff --git a/nwi/network_information_server.c b/nwi/network_information_server.c
new file mode 100644 (file)
index 0000000..00c9ff3
--- /dev/null
@@ -0,0 +1,511 @@
+/*
+ * Copyright (c) 2012, 2013 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@
+ */
+
+/*
+ * Modification History
+ *
+ * February 8, 2012            Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+#include <notify.h>
+#include <dispatch/dispatch.h>
+#include <xpc/xpc.h>
+#include <CommonCrypto/CommonDigest.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SCPrivate.h>
+
+#include "libSystemConfiguration_client.h"
+#include "libSystemConfiguration_server.h"
+
+#include <network_information.h>
+#include "network_information_priv.h"
+#include "network_information_server.h"
+
+
+#pragma mark -
+#pragma mark Globals
+
+
+/*
+ * S_nwi_info
+ *
+ * Note: all accesses should be made while running on the _nwi_server_queue()
+ */
+static libSC_info_server_t     S_nwi_info;
+
+
+/*
+ * S_debug
+ *   A boolean that enables additional logging.
+ */
+static Boolean         *S_debug        = NULL;
+static SCLoggerRef     S_logger        = NULL;
+
+
+/*
+ * S_sync_handler
+ *     ACK (in-sync or not-in-sync) updates should be posted using
+ *     this handler
+ *
+ * Note: all accesses should be made while running on the _nwi_server_queue()
+ */
+static _nwi_sync_handler_t     S_sync_handler  = NULL;
+
+
+#pragma mark -
+#pragma mark Support functions
+
+
+#ifdef NOT_YET_NEEDED
+static void
+log_xpc_object(const char *msg, xpc_object_t obj)
+{
+       char            *desc;
+
+       desc = xpc_copy_description(obj);
+       if (*S_debug) {
+               SCLoggerLog(S_logger, LOG_INFO, "%s = %s", msg, desc);
+       }
+       free(desc);
+}
+#endif
+
+
+#pragma mark -
+#pragma mark Network information server "main"
+
+
+static dispatch_queue_t
+_nwi_state_server_queue()
+{
+       static dispatch_once_t  once;
+       static dispatch_queue_t q;
+
+       dispatch_once(&once, ^{
+               q = dispatch_queue_create(NWI_SERVICE_NAME ".server", NULL);
+       });
+
+       return q;
+}
+
+
+/*
+ * _nwi_state_copy
+ *
+ * Called when a client wants a copy of the current
+ * Network information
+ *
+ * - caller must be running on the _nwi_server_queue()
+ */
+static void
+_nwi_state_copy(xpc_connection_t connection, xpc_object_t request)
+{
+       CFDataRef               data;
+       uint64_t                generation;
+       xpc_connection_t        remote;
+       xpc_object_t            reply;
+
+       remote = xpc_dictionary_get_remote_connection(request);
+       reply = xpc_dictionary_create_reply(request);
+       if (reply == NULL) {
+               SCLoggerLog(S_logger, LOG_ERR,
+                           CFSTR("<%p> _nwi_state_copy: xpc_dictionary_create_reply: failed"),
+                           connection);
+               return;
+       }
+
+       // extract data and generation #
+       data = _libSC_info_server_get_data(&S_nwi_info, connection, &generation);
+
+       if (*S_debug) {
+               const char      *proc_name;
+
+               // extract process name
+               proc_name = xpc_dictionary_get_string(request, NWI_PROC_NAME);
+               if (proc_name == NULL) {
+                       proc_name = "???";
+               }
+
+               SCLoggerLog(S_logger, LOG_INFO, CFSTR("<%p:%s[%d]> Network information copy: %lu"),
+                           connection,
+                           proc_name,
+                           xpc_connection_get_pid(connection),
+                           generation);
+       }
+
+       // return the Network information (if available)
+       if (data != NULL) {
+               xpc_dictionary_set_data(reply,
+                                       NWI_CONFIGURATION,
+                                       CFDataGetBytePtr(data),
+                                       CFDataGetLength(data));
+       }
+
+       // reply
+       xpc_connection_send_message(remote, reply);
+       xpc_release(reply);
+
+       return;
+}
+
+
+/*
+ * _nwi_state_acknowledge
+ *
+ * Called when a client wants to acknowledge processing
+ * of the Network information
+ *
+ * - caller must be running on the _nwi_server_queue()
+ */
+static void
+_nwi_state_acknowledge(xpc_connection_t connection, xpc_object_t request)
+{
+       Boolean         changed;
+       uint64_t        generation;
+
+       generation = xpc_dictionary_get_uint64(request, NWI_GENERATION);
+
+       if (*S_debug) {
+               SCLoggerLog(S_logger, LOG_INFO, CFSTR("<%p:%d> Network information ack: %lu"),
+                           connection,
+                           xpc_connection_get_pid(connection),
+                           generation);
+       }
+
+       _libSC_info_server_acknowledged(&S_nwi_info, connection, generation);
+       changed = _libSC_info_server_acknowledged(&S_nwi_info, connection, generation);
+       if (changed) {
+               Boolean         inSync;
+
+               // report change
+               inSync = _libSC_info_server_in_sync(&S_nwi_info);
+               S_sync_handler(inSync);
+       }
+
+       return;
+}
+
+
+static void
+process_request(xpc_connection_t connection, xpc_object_t request)
+{
+       int64_t         op;
+
+       op = xpc_dictionary_get_int64(request, NWI_REQUEST);
+       switch (op) {
+               case NWI_REQUEST_COPY :
+                       /*
+                        * Return the Network information
+                        */
+                       _nwi_state_copy(connection, request);
+                       break;
+
+               case NWI_REQUEST_ACKNOWLEDGE :
+                       /*
+                        * Acknowlege a [processed] Network information
+                        */
+                       _nwi_state_acknowledge(connection, request);
+
+                       break;
+               default :
+                       SCLoggerLog(S_logger, LOG_ERR,
+                                   CFSTR("<%p> unknown request : %d"),
+                                   connection,
+                                   op);
+
+                       break;
+       }
+
+       return;
+}
+
+
+static void
+process_new_connection(xpc_connection_t c)
+{
+       if (*S_debug) {
+               SCLoggerLog(S_logger, LOG_INFO, CFSTR("<%p:%d> Network information session: open"),
+                           c,
+                           xpc_connection_get_pid(c));
+       }
+
+       _libSC_info_server_open(&S_nwi_info, c);
+
+       xpc_connection_set_target_queue(c, _nwi_state_server_queue());
+
+       xpc_connection_set_event_handler(c, ^(xpc_object_t xobj) {
+               xpc_type_t      type;
+
+               type = xpc_get_type(xobj);
+               if (type == XPC_TYPE_DICTIONARY) {
+                       // process the request
+                       process_request(c, xobj);
+
+               } 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) {
+                               Boolean         changed;
+
+                               if (*S_debug) {
+                                       SCLoggerLog(S_logger, LOG_INFO, CFSTR("<%p:%d> Network information session: close"),
+                                                   c,
+                                                   xpc_connection_get_pid(c));
+                               }
+
+                               changed = _libSC_info_server_close(&S_nwi_info, c);
+                               if (changed) {
+                                       Boolean         inSync;
+
+                                       // report change
+                                       inSync = _libSC_info_server_in_sync(&S_nwi_info);
+                                       S_sync_handler(inSync);
+                               }
+
+                       } else if (xobj == XPC_ERROR_CONNECTION_INTERRUPTED) {
+                               SCLoggerLog(S_logger, LOG_ERR,
+                                           CFSTR("<%p:%d> %s"),
+                                           c,
+                                           xpc_connection_get_pid(c),
+                                           desc);
+
+                       } else {
+                               SCLoggerLog(S_logger, LOG_ERR,
+                                           CFSTR("<%p:%d> Connection error: %d : %s"),
+                                           c,
+                                           xpc_connection_get_pid(c),
+                                           xobj,
+                                           desc);
+                       }
+
+               }  else {
+                       SCLoggerLog(S_logger, LOG_ERR,
+                                   CFSTR("<%p:%d> unknown event type : %x"),
+                                   c,
+                                   xpc_connection_get_pid(c),
+                                   type);
+               }
+       });
+
+       xpc_connection_resume(c);
+
+       return;
+}
+
+
+#pragma mark -
+#pragma mark Network Information server SPIs
+
+
+__private_extern__
+void
+load_NetworkInformation(CFBundleRef            bundle,
+                       SCLoggerRef             logger,
+                       Boolean                 *bundleVerbose,
+                       _nwi_sync_handler_t     syncHandler)
+{
+       xpc_connection_t        c;
+       const char              *name;
+
+       S_debug = bundleVerbose;
+       S_logger = logger;
+
+       /*
+        * keep track of Network information acknowledgements
+        */
+       _libSC_info_server_init(&S_nwi_info);
+
+       /*
+        * save the in-sync/not-in-sync handler
+        */
+       S_sync_handler = Block_copy(syncHandler);
+
+       // create XPC listener
+       name = getenv(NWI_SERVICE_NAME);
+       if (name == NULL) {
+               name = NWI_SERVICE_NAME;
+       }
+
+       c = xpc_connection_create_mach_service(name,
+                                              _nwi_state_server_queue(),
+                                              XPC_CONNECTION_MACH_SERVICE_LISTENER);
+
+       xpc_connection_set_event_handler(c, ^(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) {
+                               SCLoggerLog(S_logger, LOG_ERR, CFSTR("Network information server: %s"), desc);
+                               xpc_release(c);
+                       } else if (event == XPC_ERROR_CONNECTION_INTERRUPTED) {
+                               SCLoggerLog(S_logger, LOG_ERR, CFSTR("Network information server: %s"), desc);
+                       } else {
+                               SCLoggerLog(S_logger, LOG_ERR,
+                                           CFSTR("Network information server: Connection error: %d : %s"),
+                                           event,
+                                           desc);
+                       }
+
+               } else {
+                       SCLoggerLog(S_logger, LOG_ERR,
+                                   CFSTR("Network information server: unknown event type : %x"),
+                                   type);
+
+               }
+       });
+
+       xpc_connection_resume(c);
+
+SCLoggerLog(S_logger, LOG_DEBUG, CFSTR("XPC server \"%s\" started"), name);
+
+       return;
+}
+
+
+__private_extern__
+void
+_nwi_state_signature(nwi_state         *state,
+                    unsigned char      *signature,
+                    size_t             signature_len)
+{
+       bzero(signature, signature_len);
+
+       if (state != NULL) {
+               CC_SHA1_CTX     ctx;
+               uint64_t        generation_save;
+               unsigned char   *sha1;
+               unsigned char   sha1_buf[CC_SHA1_DIGEST_LENGTH];
+
+               generation_save = state->generation_count;
+               state->generation_count = 0;
+
+               sha1 = (signature_len >= CC_SHA1_DIGEST_LENGTH) ? signature : sha1_buf;
+               CC_SHA1_Init(&ctx);
+               CC_SHA1_Update(&ctx,
+                              state,
+                              state->size);
+               CC_SHA1_Final(sha1, &ctx);
+               if (sha1 != signature) {
+                       bcopy(sha1, signature, signature_len);
+               }
+
+               state->generation_count = generation_save;
+       }
+
+       return;
+}
+
+
+__private_extern__
+_Bool
+_nwi_state_store(nwi_state *state)
+{
+       Boolean         in_sync;
+       uint64_t        new_generation  = 0;
+       CFDataRef       new_nwi_info    = NULL;
+       const char      *notify_key;
+
+       if (state != NULL) {
+               const UInt8     *bytes;
+               CFIndex         len;
+
+               new_generation = state->generation_count;
+
+               if (*S_debug) {
+                       SCLoggerLog(S_logger, LOG_INFO, CFSTR("Network information updated: %llu"),
+                                   new_generation);
+               }
+
+               bytes = (const UInt8 *)state;
+               len = state->size;
+
+               new_nwi_info = CFDataCreate(NULL, bytes, len);
+       }
+
+       dispatch_sync(_nwi_state_server_queue(), ^{
+               _libSC_info_server_set_data(&S_nwi_info, new_nwi_info, new_generation);
+       });
+
+       if (new_nwi_info != NULL) {
+               CFRelease(new_nwi_info);
+       }
+
+       // if anyone is keeping us in sync, they now need to catchup
+       in_sync = _libSC_info_server_in_sync(&S_nwi_info);
+       S_sync_handler(in_sync);
+
+       // and let everyone else know that the configuration has been updated
+       notify_key = nwi_state_get_notify_key();
+       if (notify_key != NULL) {
+               uint32_t        status;
+
+               _nwi_state_force_refresh();
+               status = notify_post(notify_key);
+               if (status != NOTIFY_STATUS_OK) {
+                       SCLoggerLog(S_logger, LOG_ERR, CFSTR("notify_post() failed: %d"), status);
+                       // notification posting failures are non-fatal
+               }
+       }
+
+       return TRUE;
+}
+
+
+#pragma mark -
+#pragma mark Testing
+
+
+#ifdef  MAIN
+
+int
+main(int argc, char **argv)
+{
+       static Boolean verbose = (argc > 1) ? TRUE : FALSE;
+       //      _sc_log     = FALSE;
+       _sc_verbose = (argc > 1) ? TRUE : FALSE;
+       _sc_debug   = TRUE;
+
+       load_NetworkInformation(CFBundleGetMainBundle(),        // bundle
+                               NULL,                           // SCLogger
+                               &verbose,                       // bundleVerbose
+                               ^(Boolean inSync) {             // sync handler
+                                     SCLoggerLog(NULL, LOG_INFO,
+                                           CFSTR("in sync: %s"),
+                                           inSync ? "Yes" : "No");
+                               });
+       CFRunLoopRun();
+       /* not reached */
+       exit(0);
+       return 0;
+}
+
+#endif  /* MAIN */
diff --git a/nwi/network_information_server.h b/nwi/network_information_server.h
new file mode 100644 (file)
index 0000000..bdd8b34
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2012, 2013 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@
+ */
+
+#ifndef _S_NETWORK_INFORMATION_SERVER_H
+#define _S_NETWORK_INFORMATION_SERVER_H
+
+#include <sys/cdefs.h>
+#include <stdbool.h>
+#include <mach/mach.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <network_information.h>
+
+typedef void (^_nwi_sync_handler_t)(Boolean inSync);
+
+__BEGIN_DECLS
+
+void
+load_NetworkInformation                (CFBundleRef            bundle,
+                                SCLoggerRef            logger,
+                                Boolean                *bundleVerbose,
+                                _nwi_sync_handler_t    syncHandler);
+
+void
+_nwi_state_signature           (nwi_state_t            state,
+                                unsigned char          *signature,
+                                size_t                 signature_len);
+
+_Bool
+_nwi_state_store               (nwi_state_t            state);
+
+__END_DECLS
+
+#endif /* !_S_NETWORK_INFORMATION_SERVER_H */
index 4d9e2780fef1526a18a8fea2b3beb22c9bb334ea..a5319b715e4ebcedef91ab8ae77c9cbaee355e25 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2009, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2009, 2011, 2012 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -49,7 +49,7 @@
 #include <SystemConfiguration/SCPrivate.h>
 
 #if    !TARGET_OS_IPHONE
-#include <Security/AuthSession.h>
+#include <Security/Authorization.h>
 #endif /* !TARGET_OS_IPHONE */
 
 
@@ -73,94 +73,6 @@ usage(const char *command)
 }
 
 
-static Boolean
-isAdmin()
-{
-       gid_t   groups[NGROUPS_MAX];
-       int     ngroups;
-
-       if (getuid() == 0) {
-               return TRUE;    // if "root"
-       }
-
-       ngroups = getgroups(NGROUPS_MAX, groups);
-       if(ngroups > 0) {
-               struct group    *adminGroup;
-
-               adminGroup = getgrnam("admin");
-               if (adminGroup != NULL) {
-                       gid_t   adminGid = adminGroup->gr_gid;
-                       int     i;
-
-                       for (i = 0; i < ngroups; i++) {
-                               if (groups[i] == adminGid) {
-                                       return TRUE;    // if a member of group "admin"
-                               }
-                       }
-               }
-       }
-
-       return FALSE;
-}
-
-
-#if    !TARGET_OS_IPHONE
-static void *
-__loadSecurity(void) {
-       static void *image = NULL;
-       if (NULL == image) {
-               const char      *framework              = "/System/Library/Frameworks/Security.framework/Security";
-               struct stat     statbuf;
-               const char      *suffix                 = getenv("DYLD_IMAGE_SUFFIX");
-               char            path[MAXPATHLEN];
-
-               strlcpy(path, framework, sizeof(path));
-               if (suffix) strlcat(path, suffix, sizeof(path));
-               if (0 <= stat(path, &statbuf)) {
-                       image = dlopen(path, RTLD_LAZY | RTLD_LOCAL);
-               } else {
-                       image = dlopen(framework, RTLD_LAZY | RTLD_LOCAL);
-               }
-       }
-       return (void *)image;
-}
-
-
-static OSStatus
-_SessionGetInfo(SecuritySessionId session, SecuritySessionId *sessionId, SessionAttributeBits *attributes)
-{
-       #undef SessionGetInfo
-       static typeof (SessionGetInfo) *dyfunc = NULL;
-       if (!dyfunc) {
-               void *image = __loadSecurity();
-               if (image) dyfunc = dlsym(image, "SessionGetInfo");
-       }
-       return dyfunc ? dyfunc(session, sessionId, attributes) : -1;
-}
-#define SessionGetInfo _SessionGetInfo
-#endif /* !TARGET_OS_IPHONE */
-
-static Boolean
-hasLocalConsoleAccess()
-{
-#if    !TARGET_OS_IPHONE
-       OSStatus                error;
-       SecuritySessionId       sessionID       = 0;
-       SessionAttributeBits    attributeBits   = 0;
-
-       error = SessionGetInfo(callerSecuritySession, &sessionID, &attributeBits);
-       if (error != noErr) {
-               /* Security check failed, must not permit access */
-               return FALSE;
-       }
-
-       return (attributeBits & (sessionHasGraphicAccess|sessionIsRemote)) == sessionHasGraphicAccess;
-#else  /* !TARGET_OS_IPHONE */
-       return TRUE;
-#endif /* !TARGET_OS_IPHONE */
-}
-
-
 int
 main(int argc, char **argv)
 {
@@ -179,6 +91,13 @@ main(int argc, char **argv)
        const void              **setVals       = NULL;
        CFIndex                 i;
 
+#if    !TARGET_OS_IPHONE
+       AuthorizationRef        authorization   = NULL;
+       AuthorizationFlags      flags           = kAuthorizationFlagDefaults;
+       CFMutableDictionaryRef  options;
+       OSStatus                status;
+#endif // !TARGET_OS_IPHONE
+
        /* process any arguments */
 
        while ((opt = getopt_long(argc, argv, "dvn", longopts, NULL)) != -1) {
@@ -228,12 +147,37 @@ main(int argc, char **argv)
                newSet = CFRetain(CFSTR(""));
        }
 
+#if    !TARGET_OS_IPHONE
+       status = AuthorizationCreate(NULL,
+                                    kAuthorizationEmptyEnvironment,
+                                    flags,
+                                    &authorization);
+       if (status != errAuthorizationSuccess) {
+               SCPrint(TRUE,
+                       stderr,
+                       CFSTR("AuthorizationCreate() failed: status = %d\n"),
+                       status);
+               exit (1);
+       }
 
-       prefs = SCPreferencesCreate(NULL, CFSTR("Select Set Command"), NULL);
+       options = CFDictionaryCreateMutable(NULL,
+                                           0,
+                                           &kCFTypeDictionaryKeyCallBacks,
+                                           &kCFTypeDictionaryValueCallBacks);
+       CFDictionarySetValue(options, kSCPreferencesOptionChangeNetworkSet, kCFBooleanTrue);
+       prefs = SCPreferencesCreateWithOptions(NULL, CFSTR("scselect"), NULL, authorization, options);
+       CFRelease(options);
        if (prefs == NULL) {
                SCPrint(TRUE, stderr, CFSTR("SCPreferencesCreate() failed\n"));
                exit (1);
        }
+#else  // !TARGET_OS_IPHONE
+       prefs = SCPreferencesCreate(NULL, CFSTR("scselect"), NULL);
+       if (prefs == NULL) {
+               SCPrint(TRUE, stderr, CFSTR("SCPreferencesCreate() failed\n"));
+               exit (1);
+       }
+#endif // !TARGET_OS_IPHONE
 
        sets = SCPreferencesGetValue(prefs, kSCPrefSets);
        if (sets == NULL) {
@@ -330,35 +274,43 @@ main(int argc, char **argv)
                        break;
        }
 
+       CFRelease(prefix);
        exit (0);
 
     found :
 
-       if (!(isAdmin() || hasLocalConsoleAccess())) {
-               SCPrint(TRUE, stderr,
-                       CFSTR("Only local console users and administrators can change locations\n"));
-               exit (EX_NOPERM);
-       }
-
        CFRelease(current);
        current = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), prefix, newSet);
 
        if (!SCPreferencesSetValue(prefs, kSCPrefCurrentSet, current)) {
                SCPrint(TRUE, stderr,
-                       CFSTR("SCPreferencesSetValue(...,%@,%@) failed\n"),
+                       CFSTR("SCPreferencesSetValue(...,%@,%@) failed: %s\n"),
                        kSCPrefCurrentSet,
-                       current);
+                       current,
+                       SCErrorString(SCError()));
                exit (1);
        }
 
        if (!SCPreferencesCommitChanges(prefs)) {
-               SCPrint(TRUE, stderr, CFSTR("SCPreferencesCommitChanges() failed\n"));
-               exit (1);
+               int     sc_status       = SCError();
+
+               if (sc_status == kSCStatusAccessError) {
+                       SCPrint(TRUE, stderr,
+                               CFSTR("Only local console users and administrators can change locations\n"));
+                       exit (EX_NOPERM);
+               } else {
+                       SCPrint(TRUE, stderr,
+                               CFSTR("SCPreferencesCommitChanges() failed: %s\n"),
+                               SCErrorString(sc_status));
+                       exit (1);
+               }
        }
 
        if (apply) {
                if (!SCPreferencesApplyChanges(prefs)) {
-                       SCPrint(TRUE, stderr, CFSTR("SCPreferencesApplyChanges() failed\n"));
+                       SCPrint(TRUE, stderr,
+                               CFSTR("SCPreferencesApplyChanges() failed %s\n"),
+                               SCErrorString(SCError()));
                        exit (1);
                }
        }
@@ -375,6 +327,11 @@ main(int argc, char **argv)
        CFRelease(prefix);
        CFRelease(prefs);
 
+#if    !TARGET_OS_IPHONE
+       AuthorizationFree(authorization, kAuthorizationFlagDefaults);
+//     AuthorizationFree(authorization, kAuthorizationFlagDestroyRights);
+#endif /* !TARGET_OS_IPHONE */
+
        exit (0);
        return 0;
 }
index 76fd819b716f1771ff6c5b4a2f320db7ea5dfb51..b8016e78367ddfa92c459415cecdf3616f085c59 100644 (file)
@@ -296,7 +296,7 @@ do_list(int argc, char **argv)
                        CFIndex n;
 
                        n = CFDictionaryGetCount(cached_set);
-                       if (n > 0){
+                       if (n > 0) {
                                const void *    cachedKeys_q[N_QUICK];
                                const void **   cachedKeys      = cachedKeys_q;
 
index 551289cff59394c458efb77d136d7f7b84795da6..76ba1deb45d566c2e367a8e45c1bef8ee76dcc41 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2012 Apple Inc. All rights reserved.
+ * Copyright (c) 2010-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #include "nc.h"
 #include "prefs.h"
 
+#include <SystemConfiguration/VPNConfiguration.h>
+
+#if    TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
+#include <MobileInstallation/MobileInstallation.h>
+#endif // TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
+
 #include <sys/time.h>
 
-CFStringRef                    username = NULL;
-CFStringRef                    password = NULL;
-CFStringRef                    sharedsecret = NULL;
+CFStringRef                    username        = NULL;
+CFStringRef                    password        = NULL;
+CFStringRef                    sharedsecret    = NULL;
+
+static Boolean                 ondemandwatch   = FALSE;
+static CFStringRef             ondemand_nodename = NULL;
 
 static SCNetworkConnectionRef  connection      = NULL;
 static int                     n_callback      = 0;
@@ -143,7 +152,7 @@ nc_copy_service_from_arguments(int argc, char **argv, SCNetworkSetRef set) {
        SCNetworkServiceRef     service         = NULL;
 
        if (argc == 0) {
-               serviceID = _copyStringFromSTDIN();
+               serviceID = _copyStringFromSTDIN(CFSTR("Service"), NULL);
        } else {
                serviceID = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
        }
@@ -242,6 +251,70 @@ nc_create_connection(int argc, char **argv, Boolean exit_on_failure)
        }
 }
 
+/* -----------------------------------------------------------------------------
+ ----------------------------------------------------------------------------- */
+
+static void
+nc_trigger(int argc, char **argv)
+{
+       Boolean         background      = FALSE;
+       int             i;
+       CFStringRef     hostName        = NULL;
+       int             port            = 80;
+
+       for (i = 0; i < 3 && i < argc; i++) {
+               /* Parse host name. Must be first arg. */
+               if (i == 0) {
+                       hostName = CFStringCreateWithCString(NULL, argv[i], kCFStringEncodingUTF8);
+                       continue;
+               }
+
+               /* Check for optional background flag */
+               if (strcmp(argv[i], "background") == 0) {
+                       background = TRUE;
+                       continue;
+               }
+
+               /* Parse optional port number */
+               CFStringRef str = CFStringCreateWithCString(NULL, argv[i], kCFStringEncodingUTF8);
+               if (str) {
+                       int num = CFStringGetIntValue(str);
+                       if (num) {
+                               port = num;
+                       }
+                       my_CFRelease(&str);
+               }
+       }
+
+       if (hostName) {
+               CFReadStreamRef         readStream      = NULL;
+               CFWriteStreamRef        writeStream     = NULL;
+
+               CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, hostName, port, &readStream, &writeStream);
+
+               if (background) {
+                       CFReadStreamSetProperty(readStream, CFSTR("kCFStreamNetworkServiceType"), CFSTR("kCFStreamNetworkServiceTypeBackground"));
+                       CFWriteStreamSetProperty(writeStream, CFSTR("kCFStreamNetworkServiceType"), CFSTR("kCFStreamNetworkServiceTypeBackground"));
+               }
+
+               if (readStream && writeStream) {
+                       CFReadStreamOpen(readStream);
+                       CFWriteStreamOpen(writeStream);
+                       SCPrint(TRUE, stdout, CFSTR("Opened stream to %@, port %d%s\n"), hostName, port, background ? ", background traffic class" : "");
+                       sleep(1);
+               }
+
+               my_CFRelease(&readStream);
+               my_CFRelease(&writeStream);
+       } else {
+               SCPrint(TRUE, stderr, CFSTR("Invalid or missing host name\n"));
+       }
+
+       my_CFRelease(&hostName);
+
+       exit(0);
+}
+
 /* -----------------------------------------------------------------------------
 ----------------------------------------------------------------------------- */
 static void
@@ -402,7 +475,7 @@ nc_watch(int argc, char **argv)
 
        // setup watcher
        if (doDispatch) {
-               if (!SCNetworkConnectionSetDispatchQueue(connection, dispatch_get_current_queue())) {
+               if (!SCNetworkConnectionSetDispatchQueue(connection, dispatch_get_main_queue())) {
                        SCPrint(TRUE, stderr, CFSTR("Unable to schedule watch process: %s\n"), SCErrorString(SCError()));
                        exit(1);
                }
@@ -486,6 +559,44 @@ checkOnDemandHost(SCDynamicStoreRef store, CFStringRef nodeName, Boolean retry)
        return;
 }
 
+static void
+nc_ondemand_callback(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info)
+{
+       CFStringRef             key             = NULL;
+       CFDictionaryRef         ondemand_dict   = NULL;
+       struct tm               tm_now;
+       struct timeval          tv_now;
+
+       if (CFArrayGetCount(changedKeys) < 1) {
+               return;
+       }
+
+       (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);
+
+       if (ondemand_nodename) {
+               checkOnDemandHost(store, ondemand_nodename, FALSE);
+               checkOnDemandHost(store, ondemand_nodename, TRUE);
+       } else {
+               key = CFArrayGetValueAtIndex(changedKeys, 0);
+
+               ondemand_dict = SCDynamicStoreCopyValue(store, key);
+               if (ondemand_dict) {
+                       SCPrint(TRUE, stdout, CFSTR("%@ %@\n"), kSCEntNetOnDemand, ondemand_dict);
+               } else {
+                       SCPrint(TRUE, stdout, CFSTR("%@ not configured\n"), kSCEntNetOnDemand);
+               }
+
+               my_CFRelease(&ondemand_dict);
+       }
+}
+
 static void
 nc_ondemand(int argc, char **argv)
 {
@@ -494,28 +605,64 @@ nc_ondemand(int argc, char **argv)
        CFDictionaryRef         ondemand_dict   = NULL;
        SCDynamicStoreRef       store;
 
-       store = SCDynamicStoreCreate(NULL, CFSTR("scutil --nc"), NULL, NULL);
+       store = SCDynamicStoreCreate(NULL, CFSTR("scutil --nc"), nc_ondemand_callback, NULL);
        if (store == NULL) {
                SCPrint(TRUE, stderr, CFSTR("Unable to create dynamic store: %s\n"), SCErrorString(SCError()));
                goto done;
        }
 
-       if (argc > 0) {
-               CFStringRef     nodeName;
+       if (argc == 1) {
+#if    !TARGET_IPHONE_SIMULATOR
+               if (strcmp("--refresh", argv[0]) == 0) {
+                       SCNetworkConnectionRef  connection      = NULL;
+
+                       connection = SCNetworkConnectionCreate(kCFAllocatorDefault, NULL, NULL);
+                       if (connection && SCNetworkConnectionRefreshOnDemandState(connection)) {
+                               exit_code = 0;
+                       }
+
+                       if (exit_code) {
+                               SCPrint(TRUE, stderr, CFSTR("Unable to refresh OnDemand state: %s\n"), SCErrorString(SCError()));
+                       }
 
-               nodeName = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
-               checkOnDemandHost(store, nodeName, FALSE);
-               checkOnDemandHost(store, nodeName, TRUE);
+                       my_CFRelease(&connection);
+                       goto done;
+               }
+#endif // !TARGET_IPHONE_SIMULATOR
+
+               ondemand_nodename = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+       } else if (argc != 0) {
+               SCPrint(TRUE, stderr, CFSTR("Usage: scutil --nc ondemand [-W] [hostname]\n"
+                                           "       scutil --nc ondemand -- --refresh\n"));
                goto done;
        }
 
        key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetOnDemand);
 
-       ondemand_dict = SCDynamicStoreCopyValue(store, key);
-       if (ondemand_dict) {
-               SCPrint(TRUE, stdout, CFSTR("%@ %@\n"), kSCEntNetOnDemand, ondemand_dict);
+       if (ondemand_nodename) {
+               checkOnDemandHost(store, ondemand_nodename, FALSE);
+               checkOnDemandHost(store, ondemand_nodename, TRUE);
        } else {
-               SCPrint(TRUE, stdout, CFSTR("%@ not configured\n"), kSCEntNetOnDemand);
+               ondemand_dict = SCDynamicStoreCopyValue(store, key);
+               if (ondemand_dict) {
+                       SCPrint(TRUE, stdout, CFSTR("%@ %@\n"), kSCEntNetOnDemand, ondemand_dict);
+               } else {
+                       SCPrint(TRUE, stdout, CFSTR("%@ not configured\n"), kSCEntNetOnDemand);
+               }
+       }
+
+       if (ondemandwatch) {
+               CFMutableArrayRef       keys    = NULL;
+
+               keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+               CFArrayAppendValue(keys, key);
+               SCDynamicStoreSetNotificationKeys(store, keys, NULL);
+
+               my_CFRelease(&keys);
+
+               SCDynamicStoreSetDispatchQueue(store, dispatch_get_main_queue());
+
+               CFRunLoopRun();
        }
 
        exit_code = 0;
@@ -523,63 +670,97 @@ done:
        my_CFRelease(&ondemand_dict);
        my_CFRelease(&key);
        my_CFRelease(&store);
+       my_CFRelease(&ondemand_nodename);
        exit(exit_code);
 }
 
 
 /* -----------------------------------------------------------------------------
  ----------------------------------------------------------------------------- */
-#define MAX(a, b) ((a) > (b) ? (a) : (b))
-
 CFStringRef
-copy_padded_string(CFStringRef original, int width)
+copy_padded_string(CFStringRef original, int width, CFStringRef prefix, CFStringRef suffix)
 {
        CFMutableStringRef      padded;
 
-       padded = CFStringCreateMutableCopy(NULL, 0, original);
+       padded = CFStringCreateMutable(NULL, 0);
+       if (prefix != NULL) {
+               CFStringAppend(padded, prefix);
+       }
+       if (original != NULL) {
+               CFStringAppend(padded, original);
+       }
+       if (suffix != NULL) {
+               CFStringAppend(padded, suffix);
+       }
        CFStringPad(padded, CFSTR(" "), MAX(CFStringGetLength(original), width), 0);
        return padded;
 }
 
+CFStringRef
+copy_VPN_status(SCNetworkServiceRef service)
+{
+       CFStringRef output = NULL;
+       SCNetworkConnectionStatus status = kSCNetworkConnectionInvalid;
+       SCNetworkConnectionRef service_connection = NULL;
+
+       /* Only calculate status is the service is enabled. Default is invalid. */
+       if (SCNetworkServiceGetEnabled(service)) {
+               service_connection = SCNetworkConnectionCreateWithService(NULL, service, NULL, NULL);
+               if (service_connection == NULL) goto done;
+               status = SCNetworkConnectionGetStatus(service_connection);
+       }
+
+       output = CFStringCreateWithCString(NULL, nc_status_string(status), kCFStringEncodingUTF8);
+
+done:
+       my_CFRelease(&service_connection);
+       return output;
+}
 
 static void
 nc_print_VPN_service(SCNetworkServiceRef service)
 {
-       CFStringRef type = NULL;
+       SCNetworkInterfaceRef interface = NULL;
+       CFStringRef display_name = NULL;
+       CFStringRef display_name_padded = NULL;
+       CFStringRef service_id = NULL;
+       CFStringRef service_name = NULL;
+       CFStringRef service_name_padded = NULL;
+       CFStringRef service_status = NULL;
+       CFStringRef service_status_padded = NULL;
        CFStringRef sub_type = NULL;
+       CFStringRef type = NULL;
 
        nc_get_service_type_and_subtype(service, &type, &sub_type);
 
-       CFStringRef service_name = SCNetworkServiceGetName(service);
-       if (service_name == NULL)
-               service_name = CFSTR("");
-       CFStringRef service_name_quoted = CFStringCreateWithFormat(NULL, NULL, CFSTR("\"%@\""), service_name);
-       if (service_name_quoted == NULL) {
-               service_name_quoted = CFRetain(CFSTR(""));
-       }
-       CFStringRef service_name_padded = copy_padded_string(service_name, 30);
+       service_name = SCNetworkServiceGetName(service);
+       service_name_padded = copy_padded_string(service_name, 32, CFSTR("\""), CFSTR("\""));
 
-       CFStringRef service_id   = SCNetworkServiceGetServiceID(service);
-       SCNetworkInterfaceRef interface = SCNetworkServiceGetInterface(service);
-       CFStringRef display_name = SCNetworkInterfaceGetLocalizedDisplayName(interface);
-       if (display_name == NULL)
-               display_name = CFSTR("");
-       CFStringRef display_name_padded = copy_padded_string(display_name, 18);
+       service_id = SCNetworkServiceGetServiceID(service);
 
+       interface = SCNetworkServiceGetInterface(service);
+       display_name = SCNetworkInterfaceGetLocalizedDisplayName(interface);
+       display_name_padded = copy_padded_string(display_name, 18, NULL, NULL);
+
+       service_status = copy_VPN_status(service);
+       service_status_padded = copy_padded_string(service_status, 16, CFSTR("("), CFSTR(")"));
 
        SCPrint(TRUE,
                stdout,
-               CFSTR("%@  %@ %@ %@ [%@%@%@]\n"),
+               CFSTR("%@ %@ %@ %@ %@ [%@%@%@]\n"),
                SCNetworkServiceGetEnabled(service) ? CFSTR("*") : CFSTR(" "),
+               service_status_padded,
                service_id,
                display_name_padded,
                service_name_padded,
                type,
                (sub_type == NULL) ? CFSTR("") : CFSTR(":"),
                (sub_type == NULL) ? CFSTR("") : sub_type);
-       CFRelease(service_name_quoted);
+
        CFRelease(display_name_padded);
        CFRelease(service_name_padded);
+       CFRelease(service_status_padded);
+       my_CFRelease(&service_status);
 }
 
 
@@ -609,22 +790,309 @@ nc_list(int argc, char **argv)
        exit(0);
 }
 
+/* -----------------------------------------------------------------------------
+ ----------------------------------------------------------------------------- */
+static Boolean
+nc_enable_vpntype(CFStringRef vpnType)
+{
+       Boolean                 is_enabled = FALSE;
+       Boolean                 success = FALSE;
+
+       if (vpnType == NULL) {
+               SCPrint(TRUE, stderr, CFSTR("No VPN type provided\n"));
+               goto done;
+       }
+
+       is_enabled = VPNConfigurationIsVPNTypeEnabled(vpnType);
+
+       if (is_enabled) {
+               SCPrint(TRUE, stdout, CFSTR("VPN is already enabled\n"));
+       } else {
+#if    !TARGET_OS_IPHONE
+               AuthorizationRef        authorization;
+
+               authorization = _prefs_AuthorizationCreate();
+               if ((authorization == NULL) ||
+                   !VPNConfigurationSetAuthorization(authorization)) {
+                       SCPrint(TRUE, stderr, CFSTR("VPNConfigurationSetAuthorization failed: %s\n"), SCErrorString(SCError()));
+                       goto done;
+               }
+#endif // !TARGET_OS_IPHONE
+
+               if (!VPNConfigurationEnableVPNType(vpnType)) {
+                       SCPrint(TRUE, stderr, CFSTR("VPN could not be enabled: %s\n"), SCErrorString(SCError()));
+                       goto done;
+               }
+
+#if    !TARGET_OS_IPHONE
+               _prefs_AuthorizationFree(authorization);
+#endif // !TARGET_OS_IPHONE
+
+               SCPrint(TRUE, stdout, CFSTR("VPN enabled\n"));
+       }
+       success = TRUE;
+
+done:
+       return success;
+}
+
+/* Turns a service ID or name into a vendor type, or preserves type */
+static CFStringRef
+nc_copy_vendor_type (CFStringRef input)
+{
+       SCNetworkInterfaceRef   child;
+       SCNetworkInterfaceRef   interface;
+       CFStringRef             output_name     = input;
+       SCNetworkServiceRef     service         = NULL;
+       CFStringRef             type;
+
+       if (input == NULL) {
+               goto done;
+       }
+
+       service = nc_copy_service(NULL, input);
+       if (service != NULL) {
+               interface = SCNetworkServiceGetInterface(service);
+               child = SCNetworkInterfaceGetInterface(interface);
+               type = SCNetworkInterfaceGetInterfaceType(interface);
+
+               /* Must be of type VPN */
+               if (!CFEqual(type, kSCNetworkInterfaceTypeVPN)) {
+                       output_name = NULL;
+                       goto done;
+               }
+               output_name = SCNetworkInterfaceGetInterfaceType(child);
+               goto done;
+       }
+
+done :
+       if (output_name != NULL) CFRetain(output_name);
+       my_CFRelease(&service);
+       return output_name;
+}
+
+/* -----------------------------------------------------------------------------
+ ----------------------------------------------------------------------------- */
+#if !TARGET_OS_IPHONE
+static const CFStringRef PREF_PREFIX                       = CFSTR("VPN-");
+static const CFStringRef PREF_SUFFIX                       = CFSTR(".plist");
+static void
+nc_set_application_url(CFStringRef subtype, CFStringRef directory)
+{
+       CFURLRef        directory_url           = NULL;
+       CFDataRef       directory_url_data      = NULL;
+       CFStringRef     vpnprefpath             = NULL;
+       char           *path                    = NULL;
+       CFIndex         path_len                = 0;
+
+       if (subtype == NULL || directory == NULL) {
+               goto done;
+       }
+
+       directory_url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
+                                                     directory,
+                                                     kCFURLPOSIXPathStyle,
+                                                     FALSE);
+       if (directory_url == NULL) {
+               SCPrint(TRUE, stderr, CFSTR("CFURLCreateWithFileSystemPath failed\n"));
+               goto done;
+       }
+
+       directory_url_data = CFURLCreateBookmarkData(NULL, directory_url, 0, 0, 0, 0);
+       if (directory_url_data == NULL) {
+               SCPrint(TRUE, stderr, CFSTR("CFURLCreateBookmarkData failed\n"));
+               goto done;
+       }
+
+       vpnprefpath = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@"), PREF_PREFIX, subtype, PREF_SUFFIX );
+       if (vpnprefpath == NULL) {
+               SCPrint(TRUE, stderr, CFSTR("CFStringCreateWithFormat failed\n"));
+               goto done;
+       }
+
+       path_len = CFStringGetLength(vpnprefpath) + 1;
+       path = malloc(path_len);
+       if (path == NULL) {
+               goto done;
+       }
+
+       if (!CFStringGetCString(vpnprefpath, path, path_len, kCFStringEncodingASCII)) {
+               SCPrint(TRUE, stderr, CFSTR("CFStringGetCString failed\n"));
+               goto done;
+       }
+
+       do_prefs_init();                /* initialization */
+       do_prefs_open(1, &path);        /* open prefs */
+
+       if (!SCPreferencesSetValue(prefs, CFSTR("ApplicationURL"), directory_url_data)) {
+               SCPrint(TRUE, stderr,
+                       CFSTR("SCPreferencesSetValue ApplicationURL failed, %s\n"),
+                       SCErrorString(SCError()));
+               goto done;
+       }
+
+       _prefs_save();
+
+done:
+       my_CFRelease(&directory_url);
+       my_CFRelease(&directory_url_data);
+       my_CFRelease(&vpnprefpath);
+       if (path) {
+               free(path);
+       }
+       _prefs_close();
+
+       exit(0);
+}
+#endif
+
+/* -----------------------------------------------------------------------------
+ ----------------------------------------------------------------------------- */
+static void
+nc_enablevpn(int argc, char **argv)
+{
+       CFStringRef             argument = NULL;
+       CFStringRef             vendorType = NULL;
+       int                     exit_code = 1;
+
+       if (argc == 0) {
+               SCPrint(TRUE, stderr, CFSTR("No service type or ID\n"));
+       } else {
+               argument = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+               vendorType = nc_copy_vendor_type(argument);
+               my_CFRelease(&argument);
+
+               if (!nc_enable_vpntype(vendorType)) {
+                       goto done;
+               }
+#if !TARGET_OS_IPHONE
+               if (argc >= 2) {
+                       argument = CFStringCreateWithCString(NULL, argv[1], kCFStringEncodingUTF8);
+                       nc_set_application_url(vendorType, argument);
+                       my_CFRelease(&argument);
+               }
+#endif
+       }
+
+       exit_code = 0;
+
+done:
+       my_CFRelease(&vendorType);
+       exit(exit_code);
+}
+
+
+#if TARGET_OS_EMBEDDED
+static void
+nc_print_VPN_app_info(CFStringRef appInfo, CFDictionaryRef appInfoDict)
+{
+       CFStringRef appName = NULL;
+       Boolean isEnabled = FALSE;
+       CFStringRef paddedAppInfo = NULL;
+       CFStringRef paddedAppName = NULL;
+
+       if (appInfo == NULL) {
+               return;
+       }
+
+       isEnabled = VPNConfigurationIsVPNTypeEnabled(appInfo);
+
+       CFDictionaryGetValueIfPresent(appInfoDict, CFSTR("CFBundleDisplayName"), (const void **)&appName);
+       paddedAppName = copy_padded_string((appName == NULL) ? CFSTR("") : appName, 12, NULL, NULL);
+       paddedAppInfo = copy_padded_string(appInfo, 30, NULL, NULL);
+
+       SCPrint(TRUE, stdout, CFSTR("%@ %@ [%@]\n"),
+               isEnabled ? CFSTR("(Enabled) ") : CFSTR("(Disabled)"),
+               paddedAppName,
+               appInfo);
+
+       my_CFRelease(&paddedAppName);
+       my_CFRelease(&paddedAppInfo);
+}
+#endif
+
+/* -----------------------------------------------------------------------------
+ ----------------------------------------------------------------------------- */
+#if    TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
+static void
+nc_listvpn(int argc, char **argv)
+{
+
+       CFDictionaryRef         appDict = NULL;
+       CFArrayRef              appinfo = NULL;
+       int                     i, j, count, subtypecount;
+       const void * *          keys = NULL;
+       CFMutableDictionaryRef optionsDict = NULL;
+       const void * *          values = NULL;
+       CFStringRef             vpntype = NULL;
+
+       optionsDict = CFDictionaryCreateMutable(NULL, 0,
+                                               &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+       CFDictionarySetValue(optionsDict, kLookupApplicationTypeKey, kApplicationTypeUser);
+       CFDictionarySetValue(optionsDict, kLookupAttributeKey, CFSTR("UIVPNPlugin"));
+
+       appDict = MobileInstallationLookup(optionsDict);
+       if (!isA_CFDictionary(appDict))
+               goto done;
+
+       count = CFDictionaryGetCount(appDict);
+       if (count > 0) {
+               keys = (const void * *)malloc(sizeof(CFTypeRef) * count);
+               values = (const void * *)malloc(sizeof(CFTypeRef) * count);
+
+               CFDictionaryGetKeysAndValues(appDict, keys, values);
+               for (i=0; i<count; i++) {
+                       appinfo = CFDictionaryGetValue(values[i], CFSTR("UIVPNPlugin"));
+                       if (appinfo) {
+
+
+
+                               if (isA_CFString(appinfo)) {
+                                       nc_print_VPN_app_info((CFStringRef)appinfo, (CFDictionaryRef)values[i]);
+                               }
+                               else if (isA_CFArray(appinfo)) {
+                                       subtypecount = CFArrayGetCount((CFArrayRef)appinfo);
+                                       for(j=0; j<subtypecount; j++) {
+                                               vpntype = (CFStringRef)CFArrayGetValueAtIndex((CFArrayRef)appinfo, j);
+                                               nc_print_VPN_app_info(vpntype, (CFDictionaryRef)values[i]);
+                                       }
+                               }
+                       }
+               }
+       }
+done:
+       if (keys) free(keys);
+       if (values) free(values);
+       my_CFRelease(&optionsDict);
+       my_CFRelease(&appDict);
+
+       exit(0);
+}
+#endif // TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
 
 /* -----------------------------------------------------------------------------
 ----------------------------------------------------------------------------- */
 static void
 nc_show(int argc, char **argv)
 {
-       SCNetworkServiceRef     service = NULL;
-       SCDynamicStoreRef       store = NULL;
-       int                     exit_code = 1;
-       CFStringRef             serviceID = NULL;
-       CFStringRef             iftype = NULL;
-       CFStringRef             ifsubtype = NULL;
-       CFStringRef             type_entity_key = NULL;
-       CFStringRef             subtype_entity_key = NULL;
-       CFDictionaryRef         type_entity_dict = NULL;
-       CFDictionaryRef         subtype_entity_dict = NULL;
+       SCNetworkServiceRef     service                 = NULL;
+       SCDynamicStoreRef       store                   = NULL;
+       int                     exit_code               = 1;
+       CFStringRef             serviceID               = NULL;
+       CFStringRef             iftype                  = NULL;
+       CFStringRef             ifsubtype               = NULL;
+       CFStringRef             type_entity_key         = NULL;
+       CFStringRef             subtype_entity_key      = NULL;
+       CFDictionaryRef         type_entity_dict        = NULL;
+       CFDictionaryRef         subtype_entity_dict     = NULL;
+       CFStringRef             vpnprefpath             = NULL;
+#if !TARGET_OS_IPHONE
+       CFDataRef               bookmarkData            = NULL;
+       CFURLRef                directory               = NULL;
+       Boolean                 isStale                 = FALSE;
+       char                    *path                   = NULL;
+       CFIndex                 path_len                = 0;
+#endif
 
        service = nc_copy_service_from_arguments(argc, argv, NULL);
        if (service == NULL) {
@@ -647,6 +1115,40 @@ nc_show(int argc, char **argv)
 
        nc_print_VPN_service(service);
 
+#if !TARGET_OS_IPHONE
+       vpnprefpath = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@"), PREF_PREFIX, ifsubtype, PREF_SUFFIX);
+       if (vpnprefpath == NULL) {
+               goto skipURL;
+       }
+
+       path_len = CFStringGetLength(vpnprefpath) + 1;
+       path = malloc(path_len);
+       if (path == NULL) {
+               goto skipURL;
+       }
+
+       if (!CFStringGetCString(vpnprefpath, path, path_len, kCFStringEncodingASCII)) {
+               SCPrint(TRUE, stderr, CFSTR("CFStringGetCString failed\n"));
+               goto done;
+       }
+
+       do_prefs_init();                /* initialization */
+       do_prefs_open(1, &path);        /* open prefs */
+
+       bookmarkData = SCPreferencesGetValue(prefs, CFSTR("ApplicationURL"));
+       if (bookmarkData == NULL) {
+               goto skipURL;
+       }
+
+       directory = CFURLCreateByResolvingBookmarkData(kCFAllocatorDefault, bookmarkData, 0, NULL, NULL, &isStale, NULL);
+       if (directory == NULL) {
+               goto skipURL;
+       }
+
+       SCPrint(TRUE, stdout, CFSTR("ApplicationURL: %@\n"), directory);
+skipURL:
+#endif
+
        store = SCDynamicStoreCreate(NULL, CFSTR("scutil --nc"), NULL, NULL);
        if (store == NULL) {
                SCPrint(TRUE, stderr, CFSTR("Unable to create dynamic store: %s\n"), SCErrorString(SCError()));
@@ -680,6 +1182,8 @@ done:
        my_CFRelease(&subtype_entity_dict);
        my_CFRelease(&store);
        my_CFRelease(&service);
+       my_CFRelease(&vpnprefpath);
+       _prefs_close();
        exit(exit_code);
 }
 
@@ -731,6 +1235,71 @@ done:
        exit(exit_code);
 }
 
+/* -----------------------------------------------------------------------------
+ ----------------------------------------------------------------------------- */
+static void
+nc_help(int argc, char **argv)
+{
+       SCPrint(TRUE, stderr, CFSTR("Valid commands for scutil --nc (VPN connections)\n"));
+       SCPrint(TRUE, stderr, CFSTR("Usage: scutil --nc [command]\n"));
+       SCPrint(TRUE, stderr, CFSTR("\n"));
+       SCPrint(TRUE, stderr, CFSTR("\tlist\n"));
+       SCPrint(TRUE, stderr, CFSTR("\t\tList available network connection services in the current set\n"));
+       SCPrint(TRUE, stderr, CFSTR("\n"));
+       SCPrint(TRUE, stderr, CFSTR("\tstatus <service>\n"));
+       SCPrint(TRUE, stderr, CFSTR("\t\tIndicate whether a given service is connected, as well as extended status information for the service\n"));
+       SCPrint(TRUE, stderr, CFSTR("\n"));
+       SCPrint(TRUE, stderr, CFSTR("\tshow <service>\n"));
+       SCPrint(TRUE, stderr, CFSTR("\t\tDisplay configuration information for a given service\n"));
+       SCPrint(TRUE, stderr, CFSTR("\n"));
+       SCPrint(TRUE, stderr, CFSTR("\tstatistics <service>\n"));
+       SCPrint(TRUE, stderr, CFSTR("\t\tProvide statistics on bytes, packets, and errors for a given service\n"));
+       SCPrint(TRUE, stderr, CFSTR("\n"));
+       SCPrint(TRUE, stderr, CFSTR("\tselect <service>\n"));
+       SCPrint(TRUE, stderr, CFSTR("\t\tMake the given service active in the current set. This allows it to be started\n"));
+       SCPrint(TRUE, stderr, CFSTR("\n"));
+       SCPrint(TRUE, stderr, CFSTR("\tstart <service> [--user user] [--password password] [--secret secret]\n"));
+       SCPrint(TRUE, stderr, CFSTR("\t\tStart a given service. Can take optional arguments for user, password, and secret\n"));
+       SCPrint(TRUE, stderr, CFSTR("\n"));
+       SCPrint(TRUE, stderr, CFSTR("\tstop <service>\n"));
+       SCPrint(TRUE, stderr, CFSTR("\t\tStop a given service\n"));
+       SCPrint(TRUE, stderr, CFSTR("\n"));
+       SCPrint(TRUE, stderr, CFSTR("\tsuspend <service>\n"));
+       SCPrint(TRUE, stderr, CFSTR("\t\tSuspend a given service (PPP, Modem on Hold)\n"));
+       SCPrint(TRUE, stderr, CFSTR("\n"));
+       SCPrint(TRUE, stderr, CFSTR("\tresume <service>\n"));
+       SCPrint(TRUE, stderr, CFSTR("\t\tResume a given service (PPP, Modem on Hold)\n"));
+       SCPrint(TRUE, stderr, CFSTR("\n"));
+       SCPrint(TRUE, stderr, CFSTR("\tondemand [-W] [hostname]\n"));
+       SCPrint(TRUE, stderr, CFSTR("\tondemand -- --refresh\n"));
+       SCPrint(TRUE, stderr, CFSTR("\t\tDisplay VPN on-demand information\n"));
+       SCPrint(TRUE, stderr, CFSTR("\n"));
+       SCPrint(TRUE, stderr, CFSTR("\ttrigger <hostname> [background] [port]\n"));
+       SCPrint(TRUE, stderr, CFSTR("\t\tTrigger VPN on-demand with specified hostname, and optional port and background flag\n"));
+       SCPrint(TRUE, stderr, CFSTR("\n"));
+#if TARGET_OS_EMBEDDED
+       SCPrint(TRUE, stderr, CFSTR("\tlistvpn\n"));
+       SCPrint(TRUE, stderr, CFSTR("\t\tDisplay the installed VPN applications\n"));
+       SCPrint(TRUE, stderr, CFSTR("\n"));
+#endif
+#if !TARGET_OS_IPHONE
+       SCPrint(TRUE, stderr, CFSTR("\tenablevpn <service or vpn type> [path]\n"));
+       SCPrint(TRUE, stderr, CFSTR("\t\tEnables the given VPN application type. Takes either a service or VPN type. Pass a path to set ApplicationURL\n"));
+       SCPrint(TRUE, stderr, CFSTR("\n"));
+#else
+       SCPrint(TRUE, stderr, CFSTR("\tenablevpn <service or vpn type>\n"));
+       SCPrint(TRUE, stderr, CFSTR("\t\tEnables the given VPN application type. Takes either a service or VPN type\n"));
+       SCPrint(TRUE, stderr, CFSTR("\n"));
+#endif
+       SCPrint(TRUE, stderr, CFSTR("\tdisablevpn <service or vpn type>\n"));
+       SCPrint(TRUE, stderr, CFSTR("\t\tDisables the given VPN application type. Takes either a service or VPN type\n"));
+       SCPrint(TRUE, stderr, CFSTR("\n"));
+       SCPrint(TRUE, stderr, CFSTR("\thelp\n"));
+       SCPrint(TRUE, stderr, CFSTR("\t\tDisplay available commands for --nc\n"));
+       SCPrint(TRUE, stderr, CFSTR("\n"));
+       exit(0);
+}
+
 /* -----------------------------------------------------------------------------
 ----------------------------------------------------------------------------- */
 typedef void (*nc_func) (int argc, char **argv);
@@ -739,7 +1308,12 @@ static const struct {
        char            *cmd;
        nc_func         func;
 } nc_cmds[] = {
+       { "enablevpn",          nc_enablevpn    },
+       { "help",               nc_help         },
        { "list",               nc_list         },
+#if    TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
+       { "listvpn",            nc_listvpn      },
+#endif // TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
        { "ondemand",           nc_ondemand     },
        { "resume",             nc_resume       },
        { "select",             nc_select       },
@@ -749,6 +1323,7 @@ static const struct {
        { "status",             nc_status       },
        { "stop",               nc_stop         },
        { "suspend",            nc_suspend      },
+       { "trigger",            nc_trigger      },
 };
 #define        N_NC_CMNDS      (sizeof(nc_cmds) / sizeof(nc_cmds[0]))
 
@@ -782,8 +1357,12 @@ do_nc_cmd(char *cmd, int argc, char **argv, Boolean watch)
                nc_func func;
 
                func = nc_cmds[i].func;
-               if (watch && (func == nc_status)) {
-                       func = nc_watch;
+               if (watch) {
+                       if (func == nc_status) {
+                               func = nc_watch;
+                       } else if (func == nc_ondemand) {
+                               ondemandwatch = TRUE;
+                       }
                }
                (*func)(argc, argv);
        }
index ba122042e16a110e3da0505014fae73e9c1458cf..61110c01d93cf40f854691180e0502b9c399f1f1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2011, 2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #include "net.h"
 #include "prefs.h"
 
-#include <SystemConfiguration/LinkConfiguration.h>
 
-
-#if    TARGET_OS_EMBEDDED
+#if    TARGET_OS_IPHONE
 #define        INLINE_PASSWORDS_USE_CFSTRING
-#endif // TARGET_OS_EMBEDDED
+#endif // TARGET_OS_IPHONE
 
 
 #pragma mark -
@@ -465,6 +463,7 @@ _show_interface(SCNetworkInterfaceRef interface, CFStringRef prefix, Boolean sho
        CFStringRef     if_localized_name;
        CFStringRef     if_mac_address;
        CFStringRef     if_type;
+       Boolean         isPhysicalEthernet;
        CFArrayRef      supported;
 
        if_localized_name = SCNetworkInterfaceGetLocalizedDisplayName(interface);
@@ -713,6 +712,10 @@ _show_interface(SCNetworkInterfaceRef interface, CFStringRef prefix, Boolean sho
        }
        SCPrint(TRUE, stdout, CFSTR("\n"));
 
+       isPhysicalEthernet = _SCNetworkInterfaceIsPhysicalEthernet(interface);
+       SCPrint(TRUE, stdout, CFSTR("%@  is physical ethernet = %s \n"),
+               prefix, (isPhysicalEthernet == TRUE) ? "YES" : "NO");
+
        if (configuration != NULL) {
                CFMutableDictionaryRef  effective;
 
@@ -920,6 +923,33 @@ show_interfaces(int argc, char **argv)
                                        interfaceName);
                        }
 
+                       if (_sc_debug) {
+                               CFMutableStringRef      desc;
+                               CFStringRef             str;
+
+                               str = CFCopyDescription(interface);
+                               desc = CFStringCreateMutableCopy(NULL, 0, str);
+                               CFRelease(str);
+
+                               CFStringFindAndReplace(desc,
+                                                      CFSTR(" {"),
+                                                      CFSTR("\n       {\n         "),
+                                                      CFRangeMake(0, CFStringGetLength(desc)),
+                                                      0);
+                               CFStringFindAndReplace(desc,
+                                                      CFSTR(", "),
+                                                      CFSTR(",\n         "),
+                                                      CFRangeMake(0, CFStringGetLength(desc)),
+                                                      0);
+                               CFStringFindAndReplace(desc,
+                                                      CFSTR("}"),
+                                                      CFSTR("\n       }"),
+                                                      CFRangeMake(0, CFStringGetLength(desc)),
+                                                      0);
+                               SCPrint(TRUE, stdout, CFSTR("\n     %@\n\n"), desc);
+                               CFRelease(desc);
+                       }
+
                        interface = SCNetworkInterfaceGetInterface(interface);
                        childIndex++;
                } while (interface != NULL);
index 6dfc9daa0192229b1f90280e0c3dd23c61c014fb..3149566663ab047bef80d0521a2b51007f9e0266 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2005, 2009-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2004, 2005, 2009-2011, 2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -504,6 +504,7 @@ __private_extern__
 void
 show_set(int argc, char **argv)
 {
+       CFArrayRef      interfaces;
        CFArrayRef      services;
        SCNetworkSetRef set     = NULL;
        CFStringRef     setName;
@@ -593,6 +594,25 @@ show_set(int argc, char **argv)
                CFRelease(services);
        }
 
+       interfaces = SCNetworkSetCopyAvailableInterfaces(set);
+       if (interfaces != NULL) {
+               CFIndex                 i;
+               SCNetworkInterfaceRef   interface;
+               CFIndex                 n;
+
+               SCPrint(TRUE, stdout, CFSTR("available interfaces =\n"));
+
+               n = CFArrayGetCount(interfaces);
+               for (i = 0; i < n; i++) {
+                       interface = CFArrayGetValueAtIndex(interfaces, i);
+                       SCPrint(TRUE, stdout, CFSTR(" %2d: %@ \n"),
+                               i + 1,
+                               SCNetworkInterfaceGetLocalizedDisplayName(interface));
+               }
+
+               CFRelease(interfaces);
+       }
+
        if (_sc_debug) {
                SCPrint(TRUE, stdout, CFSTR("\n%@\n"), set);
        }
index a50302e85917c85c42d2d3c956d7ae7fcbdc12dd..19507fc74c832c8ced54acefa6cccf1b5bdaabc5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2004, 2008-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2004, 2008-2012 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -286,7 +286,7 @@ _watcher(void *arg)
        }
 
        if (doDispatch) {
-               if (!SCDynamicStoreSetDispatchQueue(store, dispatch_get_current_queue())) {
+               if (!SCDynamicStoreSetDispatchQueue(store, dispatch_get_main_queue())) {
                        SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(SCError()));
                        notifyRl = NULL;
                        return NULL;
index 34e534d5a7990b0618d31b53a96a754172950817..d8761feb4879847e69ec65de11cf6fe2e192fb48 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003-2008, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2003-2008, 2011-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -69,7 +69,7 @@ __loadSecurity(void) {
 }
 
 
-__private_extern__ OSStatus
+static OSStatus
 _AuthorizationCreate(const AuthorizationRights *rights, const AuthorizationEnvironment *environment, AuthorizationFlags flags, AuthorizationRef *authorization)
 {
        #undef AuthorizationCreate
@@ -83,7 +83,7 @@ _AuthorizationCreate(const AuthorizationRights *rights, const AuthorizationEnvir
 #define AuthorizationCreate _AuthorizationCreate
 
 
-__private_extern__ OSStatus
+static OSStatus
 _AuthorizationFree(AuthorizationRef authorization, AuthorizationFlags flags)
 {
        #undef AuthorizationFree
@@ -99,28 +99,47 @@ _AuthorizationFree(AuthorizationRef authorization, AuthorizationFlags flags)
 
 /* -------------------- */
 
-
-static AuthorizationRef
-_createAuthorization()
+__private_extern__
+AuthorizationRef
+_prefs_AuthorizationCreate()
 {
        AuthorizationRef        authorization   = NULL;
-       AuthorizationFlags      flags           = kAuthorizationFlagDefaults;
-       OSStatus                status;
-
-       status = AuthorizationCreate(NULL,
-                                    kAuthorizationEmptyEnvironment,
-                                    flags,
-                                    &authorization);
-       if (status != errAuthorizationSuccess) {
-               SCPrint(TRUE,
-                       stdout,
-                       CFSTR("AuthorizationCreate() failed: status = %d\n"),
-                       status);
-               return NULL;
+
+       if (getenv("SCPREFERENCES_USE_ENTITLEMENTS") != NULL) {
+               authorization = kSCPreferencesUseEntitlementAuthorization;
+       } else {
+               AuthorizationFlags      flags   = kAuthorizationFlagDefaults;
+               OSStatus                status;
+
+               status = AuthorizationCreate(NULL,
+                                            kAuthorizationEmptyEnvironment,
+                                            flags,
+                                            &authorization);
+               if (status != errAuthorizationSuccess) {
+                       SCPrint(TRUE,
+                               stdout,
+                               CFSTR("AuthorizationCreate() failed: status = %d\n"),
+                               status);
+                       return NULL;
+               }
        }
 
        return authorization;
 }
+
+
+__private_extern__
+void
+_prefs_AuthorizationFree(AuthorizationRef authorization)
+{
+       if (authorization != kSCPreferencesUseEntitlementAuthorization) {
+               AuthorizationFree(authorization, kAuthorizationFlagDefaults);
+//             AuthorizationFree(authorization, kAuthorizationFlagDestroyRights);
+       }
+
+       return;
+}
+
 #endif /* !TARGET_OS_IPHONE */
 
 /* -------------------- */
@@ -144,9 +163,9 @@ _prefs_open(CFStringRef name, CFStringRef prefsID)
                useHelper = TRUE;
 
 #if    !TARGET_OS_IPHONE
-               authorization = _createAuthorization();
+               authorization = _prefs_AuthorizationCreate();
 #else
-               authorization = (AuthorizationRef)kSCPreferencesUseEntitlementAuthorization;
+               authorization = kSCPreferencesUseEntitlementAuthorization;
 #endif /* !TARGET_OS_IPHONE */
        }
 
@@ -228,8 +247,7 @@ _prefs_close()
 
        if (authorization != NULL) {
 #if    !TARGET_OS_IPHONE
-               AuthorizationFree(authorization, kAuthorizationFlagDefaults);
-//             AuthorizationFree(authorization, kAuthorizationFlagDestroyRights);
+               _prefs_AuthorizationFree(authorization);
 #else  /* !TARGET_OS_IPHONE */
                // Uh...if authorization isn't NULL, something went horribly wrong.
 #endif /* !TARGET_OS_IPHONE */
@@ -320,7 +338,12 @@ set_ComputerName(int argc, char **argv)
        }
 
        if (argc == 0) {
-               hostname = _copyStringFromSTDIN();
+               CFStringEncoding        old_encoding;
+               CFStringRef             old_hostname;
+
+               old_hostname = SCDynamicStoreCopyComputerName(NULL, &old_encoding);
+               hostname = _copyStringFromSTDIN(CFSTR("ComputerName"), old_hostname);
+               if (old_hostname) CFRelease(old_hostname);
        } else {
                hostname = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
        }
@@ -400,7 +423,7 @@ set_HostName(int argc, char **argv)
        }
 
        if (argc == 0) {
-               hostname = _copyStringFromSTDIN();
+               hostname = _copyStringFromSTDIN(CFSTR("HostName"), SCPreferencesGetHostName(prefs));
        } else {
                hostname = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
        }
@@ -470,7 +493,11 @@ set_LocalHostName(int argc, char **argv)
        }
 
        if (argc == 0) {
-               hostname = _copyStringFromSTDIN();
+               CFStringRef     old_hostname;
+
+               old_hostname = SCDynamicStoreCopyLocalHostName(NULL);
+               hostname = _copyStringFromSTDIN(CFSTR("LocalHostName"), old_hostname);
+               if (old_hostname) CFRelease(old_hostname);
        } else {
                hostname = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
        }
@@ -531,11 +558,37 @@ do_getPref(char *pref, int argc, char **argv)
 {
        int     i;
 
-       i = findPref(pref);
-       if (i >= 0) {
-               (*pref_keys[i].get)(argc, argv);
+       if (argc == 0) {
+               i = findPref(pref);
+               if (i >= 0) {
+                       (*pref_keys[i].get)(argc, argv);
+               }
+               return;
        }
-       return;
+
+       // Add support to parse out extended get
+       // ie. scutil --get <filename> <prefs path> <key>
+       do_prefs_init();
+       do_prefs_open(argc, argv);
+       do_prefs_get(--argc, ++argv);
+
+       if (value != NULL) {
+               CFStringRef key;
+               CFStringRef prefs_val;
+
+               key = CFStringCreateWithCString(NULL, *(++argv), kCFStringEncodingUTF8);
+               prefs_val = CFDictionaryGetValue(value, key);
+               CFRelease(key);
+
+               if (prefs_val != NULL) {
+                       SCPrint(TRUE, stdout, CFSTR("%@\n"), prefs_val);
+               } else {
+                       _prefs_close();
+                       exit(1);
+               }
+       }
+       _prefs_close();
+       exit(0);
 }
 
 
@@ -917,3 +970,43 @@ do_prefs_remove(int argc, char **argv)
        CFRelease(path);
        return;
 }
+
+/* -------------------- */
+
+#include "IPMonitorControlPrefs.h"
+
+__private_extern__
+void
+do_log(char * log, int argc, char **argv)
+{
+       if (strcmp(log, "IPMonitor")) {
+           exit(0);
+       }
+       if (argc == 0) {
+           printf("IPMonitor log is %s\n",
+                  IPMonitorControlPrefsIsVerbose() ? "on" : "off");
+       }
+       else {
+           Boolean     verbose = FALSE;
+
+           if (strcasecmp(argv[0], "on") == 0) {
+               verbose = TRUE;
+           }
+           else if (strcasecmp(argv[0], "off") == 0) {
+               verbose = FALSE;
+           }
+           else {
+               fprintf(stderr, "%s invalid, must be 'on' or 'off'\n",
+                       argv[0]);
+               exit(1);
+           }
+           if (IPMonitorControlPrefsSetVerbose(verbose) == FALSE) {
+               fprintf(stderr, "failed to set preferences\n");
+               exit(2);
+           }
+       }
+       exit(0);
+       return;
+}
+
+
index feb55bea585828beb3c5fc012012755c119e3d82..f1a3437cb6115212eb4c12d1fc97b98311ddc8af 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2005-2007 Apple Inc. All rights reserved.
+ * Copyright (c) 2003, 2005-2007, 2012, 2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -40,6 +40,9 @@ Boolean       _prefs_changed;
 
 __BEGIN_DECLS
 
+AuthorizationRef       _prefs_AuthorizationCreate      (void);
+void                   _prefs_AuthorizationFree        (AuthorizationRef authorization);
+
 Boolean        _prefs_open             (CFStringRef name, CFStringRef prefsID);
 void   _prefs_save             (void);
 void   _prefs_close            (void);
@@ -65,6 +68,7 @@ void  do_prefs_get            (int argc, char **argv);
 void   do_prefs_set            (int argc, char **argv);
 void   do_prefs_remove         (int argc, char **argv);
 
+void   do_log                  (char *pref, int argc, char **argv);
 __END_DECLS
 
 #endif /* !_PREFS_H */
index 3350639259bc65fa31f6dc04390508989bdacaf6..d0583669e1289f89785a60d54adff97a6640020c 100644 (file)
@@ -32,6 +32,9 @@
 .Br
 .Nm
 .Fl -proxy
+.Br
+.Nm
+.Fl -nc Ar nc-arguments
 .\".Br
 .\".Nm
 .\".Fl -net
@@ -85,7 +88,7 @@ The
 .Fl -dns
 option reports the current DNS configuration.
 The first listed
-.Xr resolver 5 
+.Xr resolver 5
 configuration is considered to be the
 .Qq default
 configuration.
@@ -101,6 +104,14 @@ configuration in addition to the first listed.
 The
 .Fl -proxy
 option reports the current system proxy configuration.
+.Pp
+The
+.Fl -nc
+option provides a set of commands for monitoring and interacting with VPN connections.
+Use
+.Fl -nc
+.Ar help
+for a full list of commands.
 .\".Pp
 .\"Lastly, the
 .\".Fl -net
@@ -178,7 +189,7 @@ The user-friendly name for the system.
 The local (Bonjour) host name.
 .It HostName
 The name associated with
-.Xr hostname 1 
+.Xr hostname 1
 and
 .Xr gethostname 3 .
 .El
@@ -198,6 +209,11 @@ option requires super-user access.
 Reports the current DNS configuration.
 .It Fl -proxy
 Reports the current proxy configuration.
+.It Fl -nc Ar nc-arguments
+Provides a set of commands for monitoring and interacting with VPN connections. Use
+.Fl -nc
+.Ar help
+for a full list of commands.
 .\".It Fl -net
 .\"Provides a command line interface to the
 .\".Qq network configuration .
index 7578f44cc43975e4593701e3994251fb2259cad9..c4bff2a6e9e4f98110c34444e01f69a50a68979c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2012 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -102,33 +102,77 @@ static const struct option longopts[] = {
        { "nwi",                no_argument,            NULL,   0       },
        { "prefs",              no_argument,            NULL,   0       },
        { "proxy",              no_argument,            NULL,   0       },
+       { "renew",              required_argument,      NULL,   0       },
        { "set",                required_argument,      NULL,   0       },
        { "snapshot",           no_argument,            NULL,   0       },
        { "user",               required_argument,      NULL,   0       },
        { "password",           required_argument,      NULL,   0       },
        { "secret",             required_argument,      NULL,   0       },
+       { "log",                required_argument,      NULL,   0       },
        { NULL,                 0,                      NULL,   0       }
 };
 
 
 __private_extern__
 CFStringRef
-_copyStringFromSTDIN()
+_copyStringFromSTDIN(CFStringRef prompt, CFStringRef defaultValue)
 {
        char            buf[1024];
+       int             i;
+       Boolean         is_user_prompt = (prompt != NULL && isatty(STDIN_FILENO) && isatty(STDOUT_FILENO));
        size_t          len;
+       char            *modbuf;
+       size_t          modlen;
        CFStringRef     utf8;
 
+       /* Print out a prompt to user that entry is desired */
+       if (is_user_prompt) {
+               if (defaultValue != NULL) {
+                       SCPrint(TRUE, stdout, CFSTR("%@ [%@]: "), prompt, defaultValue);
+               } else {
+                       SCPrint(TRUE, stdout, CFSTR("%@: "), prompt);
+               }
+       }
+
+       /* Get user input */
        if (fgets(buf, sizeof(buf), stdin) == NULL) {
                return NULL;
        }
 
+       /* Prepare for trim */
        len = strlen(buf);
-       if (buf[len-1] == '\n') {
-               buf[--len] = '\0';
+       modbuf = buf;
+       modlen = len;
+
+       /* Trim new-line */
+       if ((modlen > 0) && (modbuf[modlen - 1] == '\n')) {
+               modbuf[modlen - 1] = '\0';
+               modlen--;
+       }
+
+       /* If nothing was entered at the user prompt, set default */
+       if (is_user_prompt && defaultValue != NULL && modlen == 0) {
+               CFRetain(defaultValue);
+               return defaultValue;
        }
 
-       utf8 = CFStringCreateWithBytes(NULL, (UInt8 *)buf, len, kCFStringEncodingUTF8, TRUE);
+       /* Trim spaces from front */
+       while (modlen > 0 && isspace(modbuf[0])) {
+               modbuf = &modbuf[1];
+               modlen--;
+       }
+
+       /* Trim spaces  from back */
+       for (i = modlen - 1; i >= 0; i--) {
+               if (isspace(buf[i])) {
+                       buf[i] = '\0';
+                       modlen--;
+               } else {
+                       break;
+               }
+       }
+
+       utf8 = CFStringCreateWithBytes(NULL, (UInt8 *)modbuf, modlen, kCFStringEncodingUTF8, TRUE);
        return utf8;
 }
 
@@ -293,6 +337,7 @@ usage(const char *command)
        SCPrint(TRUE, stderr, CFSTR("\n"));
        SCPrint(TRUE, stderr, CFSTR("   or: %s --get pref\n"), command);
        SCPrint(TRUE, stderr, CFSTR("   or: %s --set pref [newval]\n"), command);
+       SCPrint(TRUE, stderr, CFSTR("   or: %s --get filename path key  \n"), command);
        SCPrint(TRUE, stderr, CFSTR("\tpref\tdisplay (or set) the specified preference.  Valid preferences\n"));
        SCPrint(TRUE, stderr, CFSTR("\t\tinclude:\n"));
        SCPrint(TRUE, stderr, CFSTR("\t\t\tComputerName, LocalHostName, HostName\n"));
@@ -307,6 +352,9 @@ usage(const char *command)
        SCPrint(TRUE, stderr, CFSTR("\n"));
        SCPrint(TRUE, stderr, CFSTR("   or: %s --nwi\n"), command);
        SCPrint(TRUE, stderr, CFSTR("\tshow network information\n"));
+       SCPrint(TRUE, stderr, CFSTR("\n"));
+       SCPrint(TRUE, stderr, CFSTR("   or: %s --nc\n"), command);
+       SCPrint(TRUE, stderr, CFSTR("\tshow VPN network configuration information. Use --nc help for full command list\n"));
 
        if (getenv("ENABLE_EXPERIMENTAL_SCUTIL_COMMANDS")) {
                SCPrint(TRUE, stderr, CFSTR("\n"));
@@ -321,7 +369,11 @@ usage(const char *command)
 static char *
 prompt(EditLine *el)
 {
+#if    !TARGET_IPHONE_SIMULATOR
        return "> ";
+#else  // !TARGET_IPHONE_SIMULATOR
+       return "sim> ";
+#endif // !TARGET_IPHONE_SIMULATOR
 }
 
 
@@ -336,10 +388,12 @@ main(int argc, char * const argv[])
        Boolean                 doReach = FALSE;
        Boolean                 doSnap  = FALSE;
        char                    *get    = NULL;
+       char                    *log    = NULL;
        extern int              optind;
        int                     opt;
        int                     opti;
        const char              *prog   = argv[0];
+       char                    *renew  = NULL;
        char                    *set    = NULL;
        char                    *nc_cmd = NULL;
        InputRef                src;
@@ -402,12 +456,18 @@ main(int argc, char * const argv[])
                        } else if (strcmp(longopts[opti].name, "proxy") == 0) {
                                doProxy = TRUE;
                                xStore++;
+                       } else if (strcmp(longopts[opti].name, "renew") == 0) {
+                               renew = optarg;
+                               xStore++;
                        } else if (strcmp(longopts[opti].name, "set") == 0) {
                                set = optarg;
                                xStore++;
                        } else if (strcmp(longopts[opti].name, "snapshot") == 0) {
                                doSnap = TRUE;
                                xStore++;
+                       } else if (strcmp(longopts[opti].name, "log") == 0) {
+                               log = optarg;
+                               xStore++;
                        } else if (strcmp(longopts[opti].name, "user") == 0) {
                                username = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingUTF8);
                        } else if (strcmp(longopts[opti].name, "password") == 0) {
@@ -427,6 +487,7 @@ main(int argc, char * const argv[])
                // if we are attempting to process more than one type of request
                usage(prog);
        }
+
        /* are we checking (or watching) the reachability of a host/address */
        if (doReach) {
                if (argc < 1) {
@@ -458,7 +519,11 @@ main(int argc, char * const argv[])
        }
 
        if (doSnap) {
-               if (!enablePrivateAPI || (geteuid() != 0)) {
+               if (!enablePrivateAPI
+#if    !TARGET_IPHONE_SIMULATOR
+                   || (geteuid() != 0)
+#endif // !TARGET_IPHONE_SIMULATOR
+                  ) {
                        usage(prog);
                }
 
@@ -469,9 +534,17 @@ main(int argc, char * const argv[])
 
        /* are we looking up a preference value */
        if (get) {
-               if (findPref(get) < 0) {
-                       usage(prog);
+               if (argc != 2) {
+                       if (findPref(get) < 0) {
+                               usage(prog);
+                       }
+               } else {
+                       /* need to go back one argument
+                        * for the filename */
+                       argc++;
+                       argv--;
                }
+
                do_getPref(get, argc, (char **)argv);
                /* NOT REACHED */
        }
@@ -491,6 +564,14 @@ main(int argc, char * const argv[])
                /* NOT REACHED */
        }
 
+       /* verbose log */
+       if (log != NULL) {
+               if (strcasecmp(log, "IPMonitor")) {
+                       usage(prog);
+               }
+               do_log(log, argc, (char * *)argv);
+               /* NOT REACHED */
+       }
        /* network connection commands */
        if (nc_cmd) {
                if (find_nc_cmd(nc_cmd) < 0) {
@@ -509,15 +590,15 @@ main(int argc, char * const argv[])
                        usage(prog);
                }
 
-               do_net_init();          /* initialization */
-               do_net_open(0, NULL);   /* open default prefs */
+               do_net_init();                          /* initialization */
+               do_net_open(argc, (char **)argv);       /* open prefs */
        } else if (doPrefs) {
                /* if we are going to be managing the network configuration */
                commands  = (cmdInfo *)commands_prefs;
                nCommands = nCommands_prefs;
 
-               do_dictInit(0, NULL);   /* start with an empty dictionary */
-               do_prefs_init();        /* initialization */
+               do_dictInit(0, NULL);                   /* start with an empty dictionary */
+               do_prefs_init();                        /* initialization */
                do_prefs_open(argc, (char **)argv);     /* open prefs */
        } else {
                /* if we are going to be managing the dynamic store */
@@ -528,6 +609,12 @@ main(int argc, char * const argv[])
                do_open(0, NULL);       /* open the dynamic store */
        }
 
+       /* are we trying to renew a DHCP lease */
+       if (renew != NULL) {
+               do_renew(renew);
+               /* NOT REACHED */
+       }
+
        /* allocate command input stream */
        src = (InputRef)CFAllocatorAllocate(NULL, sizeof(Input), 0);
        src->fp = stdin;
index cbffecfedae16bff13c4525c7d0ebdf8b8e7a986..4c0d0b9580ef196e2cb74f4be5824c02550a493b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2005, 2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2005, 2009, 2012 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -65,7 +65,8 @@ extern CFMutableArrayRef      watchedPatterns;
 __BEGIN_DECLS
 
 Boolean                process_line            (InputRef       src);
-CFStringRef    _copyStringFromSTDIN    ();
+CFStringRef    _copyStringFromSTDIN    (CFStringRef    prompt,
+                                        CFStringRef    defaultValue);
 
 __END_DECLS
 
index bc9160eb2502c3e8e7fbde9a0311e2fb98e08ff1..9b75f7f8ab51ff11736a8797e8cf65e37e5a1bfc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2001, 2003-2005, 2007-2012 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2003-2005, 2007-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -37,6 +37,7 @@
  */
 
 #include "scutil.h"
+#include "prefs.h"
 #include "tests.h"
 
 #include <netdb.h>
 #include <arpa/inet.h>
 
 #include <dnsinfo.h>
+#include "dnsinfo_internal.h"
 #include <network_information.h>
 #include "SCNetworkReachabilityInternal.h"
+#include <CommonCrypto/CommonDigest.h>
 
-static Boolean resolver_bypass;
+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 +66,54 @@ _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], "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-connection-on-demand") == 0) {
+                       CFDictionarySetValue(options,
+                                            kSCNetworkReachabilityOptionConnectionOnDemandBypass,
+                                            kCFBooleanTrue);
+                       continue;
                }
 
-               if (n_hints > 0) {
-                       CFDataRef       data;
+               if (strcasecmp(argv[i], "no-resolve") == 0) {
+                       CFDictionarySetValue(options,
+                                            kSCNetworkReachabilityOptionResolverBypass,
+                                            kCFBooleanTrue);
+                       resolver_bypass = TRUE;
+                       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) {
@@ -189,6 +144,8 @@ _setupReachability(int argc, char **argv, SCNetworkReachabilityContext *context)
        char                            *ip_address     = argv[0];
        const char                      *interface;
        CFMutableDictionaryRef          options         = NULL;
+       char                            *remote_address = NULL;
+       struct sockaddr_in              r_sin;
        struct sockaddr_in              sin;
        struct sockaddr_in6             sin6;
        SCNetworkReachabilityRef        target          = NULL;
@@ -209,9 +166,19 @@ _setupReachability(int argc, char **argv, SCNetworkReachabilityContext *context)
        }
 
        if (inet_aton(ip_address, &sin.sin_addr) == 1) {
-               if ((argc == 1) ||
-                   ((argc > 1) && (strlen(argv[1]) == 0))) {
-                       options = _setupReachabilityOptions(argc, argv, interface);
+               if (argc > 1) {
+                       bzero(&r_sin, sizeof(r_sin));
+                       r_sin.sin_len    = sizeof(r_sin);
+                       r_sin.sin_family = AF_INET;
+                       remote_address   = argv[1];
+               }
+
+               if ((argc == 1)
+                   || ((argc > 1) && (strlen(argv[1]) == 0))
+                   || 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,9 +205,7 @@ _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) {
@@ -259,19 +224,11 @@ _setupReachability(int argc, char **argv, SCNetworkReachabilityContext *context)
                                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);
                        }
 
-                       options = _setupReachabilityOptions(argc, argv, interface);
+                       options = _setupReachabilityOptions(argc - 2, argv + 2, interface);
                        if (options == NULL) {
                                target = SCNetworkReachabilityCreateWithAddressPair(NULL,
                                                                                    (struct sockaddr *)&sin,
@@ -304,13 +261,24 @@ _setupReachability(int argc, char **argv, SCNetworkReachabilityContext *context)
                        }
                }
        } else if (inet_pton(AF_INET6, argv[0], &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)
+                   || ((argc > 1) && (strlen(argv[1]) == 0))
+                   || inet_pton(AF_INET6, argv[1], &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 +296,12 @@ _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);
-                       }
-
                        interface = strchr(argv[1], '%');
                        if (interface != NULL) {
                                r_sin6.sin6_scope_id = if_nametoindex(interface);
                        }
 
-                       options = _setupReachabilityOptions(argc, argv, NULL);
+                       options = _setupReachabilityOptions(argc - 2, argv + 2, NULL);
                        if (options == NULL) {
                                target = SCNetworkReachabilityCreateWithAddressPair(NULL,
                                                                                    (struct sockaddr *)&sin6,
@@ -367,60 +325,28 @@ _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 {
-                               str  = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
-                               CFDictionarySetValue(options, kSCNetworkReachabilityOptionNodeName, str);
-                               CFRelease(str);
-
-                               if (context != NULL) {
-                                       context->info = "by name w/options";
-                               }
-                       }
-               } else {
-                       CFIndex         n_options;
-
-                       if (options == NULL) {
-                               options = CFDictionaryCreateMutable(NULL,
-                                                                   0,
-                                                                   &kCFTypeDictionaryKeyCallBacks,
-                                                                   &kCFTypeDictionaryValueCallBacks);
-                       }
-                       n_options = CFDictionaryGetCount(options);
+                               CFStringRef     str;
 
-                       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 (CFDictionaryGetCount(options) > n_options) {
                                if (context != NULL) {
-                                       if (n_options == 0) {
-                                               context->info = "by (node and/or serv) name";
-                                       } else {
-                                               context->info = "by (node and/or serv) name w/options";
-                                       }
+                                       context->info = "by name w/options";
                                }
-                       } else {
-                               SCPrint(TRUE, stderr, CFSTR("Must specify nodename or servname\n"));
-                               CFRelease(options);
-                               exit(1);
                        }
                }
        }
@@ -437,66 +363,6 @@ _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)
@@ -506,21 +372,21 @@ _printReachability(SCNetworkReachabilityRef target)
 
        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);
+       __SCNetworkReachabilityPrintFlags(flags);
        SCPrint(_sc_debug, stdout, CFSTR(")"));
+       SCPrint(TRUE, stdout, CFSTR("\n"));
 
        if (resolver_bypass) {
-               int if_index =
-                       SCNetworkReachabilityGetInterfaceIndex(target);
-               SCPrint(_sc_debug, stdout, CFSTR("interface index = %d"), if_index);
-       }
+               int     if_index;
 
-       SCPrint(TRUE, stdout, CFSTR("\n"));
+               if_index = SCNetworkReachabilityGetInterfaceIndex(target);
+               SCPrint(_sc_debug, stdout, CFSTR("interface index = %d\n"), if_index);
+       }
 
        return;
 }
@@ -576,6 +442,50 @@ _printNWIFlags(nwi_ifstate_flags flags)
 }
 
 
+static void
+_printNWIInfo(nwi_ifstate_t ifstate)
+{
+       nwi_ifstate_flags               ifstate_flags = nwi_ifstate_get_flags(ifstate);
+       SCNetworkReachabilityFlags      reach_flags = nwi_ifstate_get_reachability_flags(ifstate);
+       const uint8_t                   *signature;
+       int                             signature_length;
+       const struct sockaddr           *vpn_addr = nwi_ifstate_get_vpn_server(ifstate);
+
+       SCPrint(TRUE, stdout,
+               CFSTR(" %7s : flags %p"),
+               nwi_ifstate_get_ifname(ifstate),
+               ifstate_flags);
+       _printNWIFlags(ifstate_flags);
+
+       SCPrint(TRUE, stdout, CFSTR("\n           reach %p ("), reach_flags);
+       __SCNetworkReachabilityPrintFlags(reach_flags);
+       SCPrint(TRUE, stdout, CFSTR(")"));
+
+       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;
+}
+
+
 __private_extern__
 void
 do_nwi(int argc, char **argv)
@@ -591,15 +501,7 @@ do_nwi(int argc, char **argv)
        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"));
+                       _printNWIInfo(ifstate);
                } else {
                        SCPrint(TRUE, stdout, CFSTR("No network information (for %s)\n"), argv[0]);
                }
@@ -607,7 +509,9 @@ do_nwi(int argc, char **argv)
                goto done;
        }
 
-       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);
 
@@ -616,14 +520,7 @@ do_nwi(int argc, char **argv)
        }
 
        while (ifstate != NULL) {
-               nwi_ifstate_flags       flags   = nwi_ifstate_get_flags(ifstate);
-
-               SCPrint(TRUE, stdout,
-                       CFSTR(" %7s : flags %p"),
-                       nwi_ifstate_get_ifname(ifstate),
-                       flags);
-               _printNWIFlags(flags);
-               SCPrint(TRUE, stdout, CFSTR("\n"));
+               _printNWIInfo(ifstate);
                ifstate = nwi_ifstate_get_next(ifstate, AF_INET);
        }
 
@@ -635,14 +532,7 @@ do_nwi(int argc, char **argv)
        }
 
        while (ifstate != NULL) {
-               nwi_ifstate_flags       flags   = nwi_ifstate_get_flags(ifstate);
-
-               SCPrint(TRUE, stdout,
-                       CFSTR(" %7s : flags %p"),
-                       nwi_ifstate_get_ifname(ifstate),
-                       flags);
-               _printNWIFlags(flags);
-               SCPrint(TRUE, stdout, CFSTR("\n"));
+               _printNWIInfo(ifstate);
                ifstate = nwi_ifstate_get_next(ifstate, AF_INET6);
        }
 
@@ -726,7 +616,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);
                }
@@ -749,99 +639,11 @@ do_watchReachability(int argc, char **argv)
 }
 
 
-static void
-showResolver(dns_resolver_t *resolver, int index)
-{
-       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);
-       }
-
-       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 (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"));
-       }
-
-       if (resolver->search_order != 0) {
-               SCPrint(TRUE, stdout, CFSTR("  order    : %d\n"), resolver->search_order);
-       }
-
-       return;
-}
-
-
 __private_extern__
 void
 do_showDNSConfiguration(int argc, char **argv)
 {
-       dns_config_t                    *dns_config;
+       dns_config_t    *dns_config;
        SCNetworkReachabilityRef        target;
 
        dns_config = dns_configuration_copy();
@@ -852,10 +654,10 @@ do_showDNSConfiguration(int argc, char **argv)
        }
 
        if (argc > 1) {
-               int                             dns_config_index        = -1;
-               SCNetworkReachabilityFlags      flags                   = 0;
-               Boolean                         haveDNS                 = FALSE;
-               Boolean                         ok                      = FALSE;
+               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;
@@ -870,7 +672,7 @@ do_showDNSConfiguration(int argc, char **argv)
                }
 
                ok = __SC_checkResolverReachabilityInternal(&store, &flags,
-                                                           &haveDNS, targetPrivate->name, NULL,
+                                                           &haveDNS, targetPrivate->name,
                                                            &resolver_if_index, &dns_config_index);
 
                if (!ok) {
@@ -887,29 +689,15 @@ do_showDNSConfiguration(int argc, char **argv)
                        resolver = dns_config->scoped_resolver[dns_config_index];
                }
 
-               showResolver(resolver, dns_config_index + 1);
+               _dns_resolver_print(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];
-
-                       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"));
-
-                       for (i = 0; i < dns_config->n_scoped_resolver; i++) {
-                               dns_resolver_t  *resolver       = dns_config->scoped_resolver[i];
+               _dns_configuration_print(dns_config);
+       }
 
-                               showResolver(resolver, i + 1);
-                       }
-               }
+       if (_sc_debug) {
+               SCPrint(TRUE, stdout, CFSTR("\ngeneration = %lu\n"), dns_config->generation);
        }
 
        dns_configuration_free(dns_config);
@@ -924,8 +712,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 +728,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;
@@ -1044,6 +846,117 @@ do_snapshot(int argc, char **argv)
 }
 
 
+__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 +1029,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 +1039,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
index 6b5c0e9ad8e9a00f187fd1022255a6419e85984a..996a64e814483be4a705bbc469bcbd0a933ab197 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2001, 2004, 2007, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2004, 2007, 2011, 2012 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -42,6 +42,7 @@ __BEGIN_DECLS
 
 void   do_checkReachability            (int argc, char **argv);
 void   do_watchReachability            (int argc, char **argv);
+void   do_renew                        (char *interface);
 void   do_showDNSConfiguration         (int argc, char **argv);
 void   do_showProxyConfiguration       (int argc, char **argv);
 void   do_snapshot                     (int argc, char **argv);
diff --git a/tests/Makefile b/tests/Makefile
new file mode 100644 (file)
index 0000000..5079e8f
--- /dev/null
@@ -0,0 +1,24 @@
+PLATFORM=iphoneos
+
+ifeq ($(PLATFORM),iphoneos)
+ARCHS=armv7
+endif
+
+ifeq ($(PLATFORM),macosx)
+ARCHS=i386 x86_64
+endif
+
+FRAMEWORKS=CoreFoundation SystemConfiguration CFNetwork
+SDK=$(PLATFORM).internal
+SYSROOT=$(shell xcodebuild -version -sdk $(SDK) Path)
+PF_INC=-F$(SYSROOT)/System/Library/PrivateFrameworks
+ARCH_FLAGS=$(foreach a,$(ARCHS),-arch $(a))
+FW_FLAGS=$(foreach f,$(FRAMEWORKS),-framework $(f))
+CC=xcrun -sdk $(SDK) cc
+
+ReachabilityTester : ReachabilityTester.c
+       $(CC) $(ARCH_FLAGS) -isysroot $(SYSROOT) $(PF_INC) $(FW_FLAGS) -g -o $@ $<
+       tar -czf $@.tgz $@ $@.dSYM $<
+
+clean :
+       rm -rf ReachabilityTester ReachabilityTester.dSYM ReachabilityTester.tgz
diff --git a/tests/ReachabilityTester.c b/tests/ReachabilityTester.c
new file mode 100644 (file)
index 0000000..41ee485
--- /dev/null
@@ -0,0 +1,316 @@
+/*
+ * Copyright (c) 2012 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 <stdio.h>
+#include <pthread.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <CFNetwork/CFNetwork.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+
+static SCNetworkReachabilityRef g_reachability = NULL;
+static CFURLRef g_url = NULL;
+static CFReadStreamRef g_rstream = NULL;
+
+static char *
+string2CString(CFStringRef str)
+{
+    UInt8 *buffer;
+    CFIndex clen;
+    CFRange r = CFRangeMake(0, CFStringGetLength(str));
+
+    if (CFStringGetBytes(str, r, kCFStringEncodingASCII, 0, false, NULL, 0, &clen) > 0) {
+       buffer = (UInt8 *)CFAllocatorAllocate(kCFAllocatorDefault, (clen + 1) * sizeof(UInt8), 0);
+
+       if (buffer != NULL) {
+           if (CFStringGetBytes(str, r, kCFStringEncodingASCII, 0, false, buffer, clen, NULL)) {
+               buffer[clen] = '\0';
+               return (char *)buffer;
+           }
+           CFAllocatorDeallocate(kCFAllocatorDefault, buffer);
+       }
+    }
+
+    return NULL;
+}
+
+static void
+printReachabilityFlags(const char *source, SCNetworkReachabilityFlags flags)
+{
+    printf("[%s] Reachability flags (%x):\n", source, flags);
+    if (flags & kSCNetworkReachabilityFlagsTransientConnection) {
+       printf("[%s]  transient\n", source);
+    }
+    if (flags & kSCNetworkReachabilityFlagsReachable) {
+       printf("[%s]  reachable\n", source);
+    }
+    if (flags & kSCNetworkReachabilityFlagsConnectionRequired) {
+       printf("[%s]  connection required\n", source);
+    }
+    if (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) {
+       printf("[%s]  connection on traffic\n", source);
+    }
+    if (flags & kSCNetworkReachabilityFlagsInterventionRequired) {
+       printf("[%s]  intervention required\n", source);
+    }
+    if (flags & kSCNetworkReachabilityFlagsConnectionOnDemand) {
+       printf("[%s]  connection on demand\n", source);
+    }
+    if (flags & kSCNetworkReachabilityFlagsIsLocalAddress) {
+       printf("[%s]  local address\n", source);
+    }
+    if (flags & kSCNetworkReachabilityFlagsIsDirect) {
+       printf("[%s]  direct\n", source);
+    }
+#if TARGET_OS_EMBEDDED
+    if (flags & kSCNetworkReachabilityFlagsIsWWAN) {
+       printf("[%s]  wwan\n", source);
+    }
+#endif
+}
+
+static void
+handleReachabilityUpdate(
+       SCNetworkReachabilityRef target,
+       SCNetworkReachabilityFlags flags,
+       void *info)
+{
+    printReachabilityFlags("RunLoop", flags);
+}
+
+static SCNetworkReachabilityRef
+createReachabilityWithCFHost(CFHostRef theHost)
+{
+    SCNetworkReachabilityRef reachRef = NULL;
+    Boolean resolved = FALSE;
+    CFArrayRef addrs = CFHostGetAddressing(theHost, &resolved);
+
+    if (resolved && addrs != NULL && CFArrayGetCount(addrs) > 0) {
+       CFDataRef addr = (CFDataRef)CFArrayGetValueAtIndex(addrs, 0);
+
+       reachRef = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (struct sockaddr *)CFDataGetBytePtr(addr));
+    } else {
+       CFArrayRef names = CFHostGetNames(theHost, NULL);
+
+       if (names != NULL && CFArrayGetCount(names) > 0) {
+           CFStringRef host = (CFStringRef)CFArrayGetValueAtIndex(names, 0);
+           char *chost = string2CString(host);
+
+           reachRef = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, chost);
+
+           CFAllocatorDeallocate(kCFAllocatorDefault, chost);
+       }
+    }
+
+    if (reachRef != NULL) {
+       SCNetworkReachabilityContext reach_ctx = { 0, NULL, NULL, NULL, NULL };
+       SCNetworkReachabilitySetCallback(reachRef, handleReachabilityUpdate,
+                                        &reach_ctx);
+       CFShow(reachRef);
+    } else {
+       fprintf(stderr, "Failed to create a reachability object\n");
+    }
+
+    return reachRef;
+}
+
+static void
+handleDownload(CFReadStreamRef rstream, CFStreamEventType eventType, void *info)
+{
+    Boolean done = FALSE;
+
+    if (eventType == kCFStreamEventHasBytesAvailable) {
+       UInt8 buffer[1024];
+
+       while (CFReadStreamHasBytesAvailable(rstream)) {
+           CFIndex count = CFReadStreamRead(rstream, buffer, sizeof(buffer));
+           if (count == 0) {
+               done = TRUE;
+           }
+       }
+    } else if (eventType == kCFStreamEventEndEncountered) {
+       printf("Download completed\n");
+       done = TRUE;
+    } else if (eventType == kCFStreamEventErrorOccurred) {
+       printf("Download error\n");
+       done = TRUE;
+    } else {
+       printf("Got stream event: %lu\n", eventType);
+    }
+
+    if (!done) {
+       return;
+    }
+
+    CFReadStreamUnscheduleFromRunLoop(rstream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
+    CFReadStreamClose(rstream);
+    CFRelease(rstream);
+
+    g_rstream = NULL;
+}
+
+static void
+startDownload(void)
+{
+    CFHTTPMessageRef request = CFHTTPMessageCreateRequest(kCFAllocatorDefault, CFSTR("GET"), g_url, kCFHTTPVersion1_1);
+    CFReadStreamRef rstream = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, request);
+    CFStreamClientContext ctx = { 0, NULL, NULL, NULL, NULL };
+
+    printf("Starting download\n");
+
+    CFReadStreamSetClient(rstream,
+                         kCFStreamEventEndEncountered | kCFStreamEventErrorOccurred | kCFStreamEventHasBytesAvailable, 
+                         handleDownload,
+                         &ctx);
+
+    CFReadStreamScheduleWithRunLoop(rstream, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
+
+    CFReadStreamOpen(rstream);
+
+    g_rstream = rstream;
+
+    CFRelease(request);
+}
+
+static void
+downloadTimerFired(CFRunLoopTimerRef timer, void *info)
+{
+    if (g_rstream != NULL) {
+       handleDownload(g_rstream, kCFStreamEventErrorOccurred, NULL);
+    }
+
+
+    SCNetworkReachabilityUnscheduleFromRunLoop(g_reachability, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
+
+    startDownload();
+
+    SCNetworkReachabilityScheduleWithRunLoop(g_reachability, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
+}
+
+static void
+startDownloadLoop(void)
+{
+    CFRunLoopTimerRef timer;
+    CFRunLoopTimerContext ctx = { 0, NULL, NULL, NULL, NULL };
+    CFAbsoluteTime now = CFAbsoluteTimeGetCurrent();
+
+    timer = CFRunLoopTimerCreate(kCFAllocatorDefault, 
+                                now + 0.1,
+                                7.0,
+                                0,
+                                0,
+                                downloadTimerFired,
+                                &ctx);
+
+    CFRunLoopAddTimer(CFRunLoopGetMain(), timer, kCFRunLoopCommonModes);
+}
+
+static void *
+reachabilityLoop(void *arg)
+{
+    while (1) {
+       SCNetworkReachabilityFlags flags;
+       SCNetworkReachabilityGetFlags(g_reachability, &flags);
+
+       printReachabilityFlags("thread", flags);
+
+       sleep(1);
+    }
+
+    return NULL;
+}
+
+static void
+startReachabilityThread(void)
+{
+    pthread_attr_t tattr;
+    pthread_t th;
+
+    pthread_attr_init(&tattr);
+    pthread_create(&th, &tattr, reachabilityLoop, NULL);
+    pthread_attr_destroy(&tattr);
+}
+
+static void
+addressResolutionCallback(CFHostRef theHost, CFHostInfoType typeInfo, const CFStreamError *error, void *info)
+{
+    g_reachability = createReachabilityWithCFHost(theHost);
+
+    if (g_reachability != NULL) {
+       startDownloadLoop();
+       startReachabilityThread();
+    }
+
+    CFRelease(theHost);
+}
+
+static void
+startAddressResolution(Boolean resolve)
+{
+    CFStringRef hostStr = CFURLCopyHostName(g_url);
+    CFHostRef cfhost = CFHostCreateWithName(kCFAllocatorDefault, hostStr);
+    CFHostClientContext ctx = { 0, NULL, NULL, NULL, NULL };
+    CFStreamError err;
+
+    if (resolve) {
+       CFHostSetClient(cfhost, addressResolutionCallback, &ctx);
+       CFHostScheduleWithRunLoop(cfhost, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
+       CFHostStartInfoResolution(cfhost, kCFHostAddresses, &err);
+    } else {
+       addressResolutionCallback(cfhost, kCFHostNames, NULL, NULL);
+    }
+
+    CFRelease(hostStr);
+}
+
+int
+main(int argc, char *argv[])
+{
+    CFStringRef urlStr;
+    Boolean resolve = TRUE;
+
+    if (argc < 2) {
+       fprintf(stderr, "usage: %s <url> [-byname]", argv[0]);
+       return 1;
+    }
+
+    urlStr = CFStringCreateWithCString(kCFAllocatorDefault, argv[1], kCFStringEncodingASCII);
+    g_url = CFURLCreateWithString(kCFAllocatorDefault, urlStr, NULL);
+
+    CFRelease(urlStr);
+
+    if (argc > 2 && !strcmp(argv[2], "-byname")) {
+       resolve = FALSE;
+    }
+
+    startAddressResolution(resolve);
+
+    CFRunLoopRun();
+
+    CFRelease(g_url);
+
+    SCNetworkReachabilityUnscheduleFromRunLoop(g_reachability, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
+    CFRelease(g_reachability);
+
+    return 0;
+}