]> git.saurik.com Git - apple/configd.git/blob - Plugins/SimulatorSupport/simulator_support.c
configd-596.12.tar.gz
[apple/configd.git] / Plugins / SimulatorSupport / simulator_support.c
1 /*
2 * Copyright (c) 2013 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 /*
25 * Modification History
26 *
27 * March 15, 2013 Allan Nathanson <ajn@apple.com>
28 * - initial revision
29 */
30
31
32 #include <SystemConfiguration/SystemConfiguration.h>
33 #include <SystemConfiguration/SCPrivate.h>
34 #include <SystemConfiguration/SCValidation.h>
35
36 #include <dns_sd.h>
37 #ifndef kDNSServiceCompMulticastDNS
38 #define kDNSServiceCompMulticastDNS "MulticastDNS"
39 #endif
40 #ifndef kDNSServiceCompPrivateDNS
41 #define kDNSServiceCompPrivateDNS "PrivateDNS"
42 #endif
43
44 #include "cache.h"
45
46
47 static Boolean _verbose = FALSE;
48 static CFMutableArrayRef mirror_keys = NULL;
49 static CFMutableArrayRef mirror_patterns = NULL;
50 static SCDynamicStoreRef store_host = NULL;
51 static SCDynamicStoreRef store_sim = NULL;
52
53
54 #pragma mark -
55 #pragma mark iOS Simulator Support
56
57
58 static void
59 mirror(SCDynamicStoreRef store, CFArrayRef changes, void *info)
60 {
61 CFDictionaryRef content_host;
62 CFDictionaryRef content_sim;
63 CFIndex i;
64 CFIndex n;
65
66 n = CFArrayGetCount(changes);
67 if (n == 0) {
68 // if no changes
69 return;
70 }
71
72 // capture "host" content
73 if (info == NULL) {
74 content_host = SCDynamicStoreCopyMultiple(store_host, changes, NULL);
75 } else {
76 content_host = (CFDictionaryRef)info;
77 }
78
79 // capture [current] "sim" content
80 content_sim = SCDynamicStoreCopyMultiple(store_sim, changes, NULL);
81
82 // update
83 cache_open();
84 for (i = 0; i < n; i++) {
85 CFStringRef key;
86 CFPropertyListRef val;
87
88 key = CFArrayGetValueAtIndex(changes, i);
89 val = (content_host != NULL) ? CFDictionaryGetValue(content_host, key) : NULL;
90 if (val != NULL) {
91 // if "host" content changed
92 cache_SCDynamicStoreSetValue(store_sim, key, val);
93 } else {
94 // if no "host" content
95 val = (content_sim != NULL) ? CFDictionaryGetValue(content_sim, key) : NULL;
96 if (val != NULL) {
97 // if we need to remove the "sim" content
98 cache_SCDynamicStoreRemoveValue(store_sim, key);
99 } else {
100 // if no "sim" content to remove, just notify
101 cache_SCDynamicStoreNotifyValue(store_sim, key);
102 }
103 }
104 }
105 cache_write(store_sim);
106 cache_close();
107
108 // cleanup
109 if ((info == NULL) && (content_host != NULL)) {
110 CFRelease(content_host);
111 }
112 if (content_sim != NULL) {
113 CFRelease(content_sim);
114 }
115
116 return;
117 }
118
119
120 static void
121 mirror_setup()
122 {
123 CFStringRef key;
124 CFStringRef pattern;
125
126 mirror_keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
127 mirror_patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
128
129 // Plugin:InterfaceNamer
130 key = SCDynamicStoreKeyCreate(NULL,
131 CFSTR("%@" "InterfaceNamer"),
132 kSCDynamicStoreDomainPlugin);
133 CFArrayAppendValue(mirror_keys, key);
134 CFRelease(key);
135
136 // Setup:/System
137 // key = SCDynamicStoreKeyCreateComputerName(NULL);
138 // CFArrayAppendValue(mirror_keys, key);
139 // CFRelease(key);
140
141 // Setup:/Network
142 // key = SCDynamicStoreKeyCreateHostNames(NULL);
143 // CFArrayAppendValue(mirror_keys, key);
144 // CFRelease(key);
145
146 // Setup:/Network/Global/.*
147 pattern = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
148 kSCDynamicStoreDomainSetup,
149 kSCCompAnyRegex);
150 CFArrayAppendValue(mirror_patterns, pattern);
151 CFRelease(pattern);
152
153 // Setup:/Network/Service/.*
154 // State:/Network/Service/.*
155 pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
156 kSCCompAnyRegex,
157 CFSTR(".*"),
158 NULL);
159 CFArrayAppendValue(mirror_patterns, pattern);
160 CFRelease(pattern);
161
162 // Setup:/Network/Interface/.*
163 // State:/Network/Interface/.*
164 pattern = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
165 kSCCompAnyRegex,
166 CFSTR(".*"),
167 NULL);
168 CFArrayAppendValue(mirror_patterns, pattern);
169 CFRelease(pattern);
170
171 // State:/Network/MulticastDNS
172 key = SCDynamicStoreKeyCreate(NULL, CFSTR("%@/%@/%@"),
173 kSCDynamicStoreDomainState,
174 kSCCompNetwork,
175 CFSTR(kDNSServiceCompMulticastDNS));
176 CFArrayAppendValue(mirror_keys, key);
177 CFRelease(key);
178
179 // State:/Network/PrivateDNS
180 key = SCDynamicStoreKeyCreate(NULL, CFSTR("%@/%@/%@"),
181 kSCDynamicStoreDomainState,
182 kSCCompNetwork,
183 CFSTR(kDNSServiceCompPrivateDNS));
184 CFArrayAppendValue(mirror_keys, key);
185 CFRelease(key);
186
187 return;
188 }
189
190
191 #define N_QUICK 64
192
193
194 __private_extern__
195 void
196 prime_SimulatorSupport()
197 {
198 CFDictionaryRef content_host;
199 CFIndex n;
200
201 SCLog(_verbose, LOG_DEBUG, CFSTR("prime() called"));
202
203 // copy current content from base OS store to _Sim store
204 content_host = SCDynamicStoreCopyMultiple(store_host, mirror_keys, mirror_patterns);
205 CFRelease(mirror_keys);
206 mirror_keys = NULL;
207 CFRelease(mirror_patterns);
208 mirror_patterns = NULL;
209
210 if (content_host == NULL) {
211 return;
212 }
213
214 n = CFDictionaryGetCount(content_host);
215 if (n > 0) {
216 CFArrayRef changes;
217 const void * keys_host_q[N_QUICK];
218 const void ** keys_host = keys_host_q;
219
220 if (n > (CFIndex)(sizeof(keys_host_q) / sizeof(CFStringRef))) {
221 keys_host = CFAllocatorAllocate(NULL, n * sizeof(CFStringRef), 0);
222 }
223
224 CFDictionaryGetKeysAndValues(content_host, keys_host, NULL);
225
226 changes = CFArrayCreate(NULL, keys_host, n, &kCFTypeArrayCallBacks);
227 mirror(store_host, changes, (void *)content_host);
228 CFRelease(changes);
229
230 if (keys_host != keys_host_q) {
231 CFAllocatorDeallocate(NULL, keys_host);
232 }
233 }
234
235 CFRelease(content_host);
236 return;
237 }
238
239
240 __private_extern__
241 void
242 load_SimulatorSupport(CFBundleRef bundle, Boolean bundleVerbose)
243 {
244 Boolean ok;
245 CFMutableDictionaryRef options;
246 CFRunLoopSourceRef rls;
247
248 if (bundleVerbose) {
249 _verbose = TRUE;
250 }
251
252 SCLog(_verbose, LOG_DEBUG, CFSTR("load() called"));
253 SCLog(_verbose, LOG_DEBUG, CFSTR(" bundle ID = %@"), CFBundleGetIdentifier(bundle));
254
255 // setup
256 mirror_setup();
257
258 // setup SCDynamicStore mirroring (from "host")
259 options = CFDictionaryCreateMutable(NULL,
260 0,
261 &kCFTypeDictionaryKeyCallBacks,
262 &kCFTypeDictionaryValueCallBacks);
263 CFDictionarySetValue(options, kSCDynamicStoreUseHostServer, kCFBooleanTrue);
264 store_host = SCDynamicStoreCreateWithOptions(NULL,
265 CFSTR("SimulatorSupport(host)"),
266 options,
267 mirror,
268 NULL);
269 CFRelease(options);
270 assert(store_host != NULL);
271
272 ok = SCDynamicStoreSetNotificationKeys(store_host, mirror_keys, mirror_patterns);
273 assert(ok);
274
275 rls = SCDynamicStoreCreateRunLoopSource(NULL, store_host, 0);
276 assert(rls != NULL);
277
278 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
279 CFRelease(rls);
280
281 // setup SCDynamicStore mirroring (to "iOS Simulator")
282 store_sim = SCDynamicStoreCreate(NULL,
283 CFSTR("SimulatorSupport(sim)"),
284 NULL,
285 NULL);
286
287 return;
288 }
289
290
291 #ifdef MAIN
292
293
294 #pragma mark -
295 #pragma mark Standalone test code
296
297
298 int
299 main(int argc, char **argv)
300 {
301 _sc_log = FALSE;
302 _sc_verbose = (argc > 1) ? TRUE : FALSE;
303
304 load_SimulatorSupport(CFBundleGetMainBundle(), (argc > 1) ? TRUE : FALSE);
305 prime_SimulatorSupport();
306 CFRunLoopRun();
307 // not reached
308 exit(0);
309 return 0;
310 }
311 #endif