/* * Copyright (c) 2013, 2015-2018 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 * - initial revision */ #include #include #include #include #include #include #if TARGET_OS_SIMULATOR && !TARGET_OS_IOSMAC static CFMutableArrayRef mirror_keys = NULL; static CFMutableArrayRef mirror_patterns = NULL; static SCDynamicStoreRef store_host = NULL; static SCDynamicStoreRef store_sim = NULL; #pragma mark - #pragma mark Logging /* * Logging */ __private_extern__ os_log_t __log_SimulatorSupport(void) { static os_log_t log = NULL; if (log == NULL) { log = os_log_create("com.apple.SystemConfiguration", "SimulatorSupport"); } return log; } #pragma mark - #pragma mark iOS Simulator Support static void mirror(SCDynamicStoreRef store, CFArrayRef changes, void *info) { #pragma unused(store) 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 _SCDynamicStoreCacheOpen(store); 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 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 SCDynamicStoreRemoveValue(store_sim, key); } else { // if no "sim" content to remove, just notify SCDynamicStoreNotifyValue(store_sim, key); } } } _SCDynamicStoreCacheCommitChanges(store_sim); _SCDynamicStoreCacheClose(store); // 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; SC_log(LOG_DEBUG, "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) { #pragma unused(bundleVerbose) Boolean ok; CFMutableDictionaryRef options; CFRunLoopSourceRef rls; SC_log(LOG_DEBUG, "load() called"); SC_log(LOG_DEBUG, " 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 #endif // TARGET_OS_SIMULATOR && !TARGET_OS_IOSMAC