]>
Commit | Line | Data |
---|---|---|
5e9ce69e | 1 | /* |
942cecd7 | 2 | * Copyright (c) 2013, 2015, 2016 Apple Inc. All rights reserved. |
5e9ce69e A |
3 | * |
4 | * @APPLE_LICENSE_HEADER_START@ | |
9de8ab86 | 5 | * |
5e9ce69e A |
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. | |
9de8ab86 | 12 | * |
5e9ce69e A |
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. | |
9de8ab86 | 20 | * |
5e9ce69e A |
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> | |
942cecd7 | 37 | #include <dns_sd_private.h> |
5e9ce69e A |
38 | |
39 | #include "cache.h" | |
40 | ||
41 | ||
5e9ce69e A |
42 | static CFMutableArrayRef mirror_keys = NULL; |
43 | static CFMutableArrayRef mirror_patterns = NULL; | |
44 | static SCDynamicStoreRef store_host = NULL; | |
45 | static SCDynamicStoreRef store_sim = NULL; | |
46 | ||
47 | ||
942cecd7 A |
48 | #pragma mark - |
49 | #pragma mark Logging | |
50 | ||
51 | ||
52 | /* | |
53 | * Logging | |
54 | */ | |
55 | __private_extern__ os_log_t | |
56 | __log_SimulatorSupport() | |
57 | { | |
58 | static os_log_t log = NULL; | |
59 | ||
60 | if (log == NULL) { | |
61 | log = os_log_create("com.apple.SystemConfiguration", "SimulatorSupport"); | |
62 | } | |
63 | ||
64 | return log; | |
65 | } | |
66 | ||
67 | ||
5e9ce69e A |
68 | #pragma mark - |
69 | #pragma mark iOS Simulator Support | |
70 | ||
71 | ||
72 | static void | |
73 | mirror(SCDynamicStoreRef store, CFArrayRef changes, void *info) | |
74 | { | |
75 | CFDictionaryRef content_host; | |
76 | CFDictionaryRef content_sim; | |
77 | CFIndex i; | |
78 | CFIndex n; | |
79 | ||
80 | n = CFArrayGetCount(changes); | |
81 | if (n == 0) { | |
82 | // if no changes | |
83 | return; | |
84 | } | |
85 | ||
86 | // capture "host" content | |
87 | if (info == NULL) { | |
88 | content_host = SCDynamicStoreCopyMultiple(store_host, changes, NULL); | |
89 | } else { | |
90 | content_host = (CFDictionaryRef)info; | |
91 | } | |
92 | ||
93 | // capture [current] "sim" content | |
94 | content_sim = SCDynamicStoreCopyMultiple(store_sim, changes, NULL); | |
95 | ||
96 | // update | |
97 | cache_open(); | |
98 | for (i = 0; i < n; i++) { | |
99 | CFStringRef key; | |
100 | CFPropertyListRef val; | |
101 | ||
102 | key = CFArrayGetValueAtIndex(changes, i); | |
103 | val = (content_host != NULL) ? CFDictionaryGetValue(content_host, key) : NULL; | |
104 | if (val != NULL) { | |
105 | // if "host" content changed | |
106 | cache_SCDynamicStoreSetValue(store_sim, key, val); | |
107 | } else { | |
108 | // if no "host" content | |
109 | val = (content_sim != NULL) ? CFDictionaryGetValue(content_sim, key) : NULL; | |
110 | if (val != NULL) { | |
111 | // if we need to remove the "sim" content | |
112 | cache_SCDynamicStoreRemoveValue(store_sim, key); | |
113 | } else { | |
114 | // if no "sim" content to remove, just notify | |
115 | cache_SCDynamicStoreNotifyValue(store_sim, key); | |
116 | } | |
117 | } | |
118 | } | |
119 | cache_write(store_sim); | |
120 | cache_close(); | |
121 | ||
122 | // cleanup | |
123 | if ((info == NULL) && (content_host != NULL)) { | |
124 | CFRelease(content_host); | |
125 | } | |
126 | if (content_sim != NULL) { | |
127 | CFRelease(content_sim); | |
128 | } | |
129 | ||
130 | return; | |
131 | } | |
132 | ||
133 | ||
134 | static void | |
135 | mirror_setup() | |
136 | { | |
137 | CFStringRef key; | |
138 | CFStringRef pattern; | |
139 | ||
140 | mirror_keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); | |
141 | mirror_patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); | |
142 | ||
143 | // Plugin:InterfaceNamer | |
144 | key = SCDynamicStoreKeyCreate(NULL, | |
145 | CFSTR("%@" "InterfaceNamer"), | |
146 | kSCDynamicStoreDomainPlugin); | |
147 | CFArrayAppendValue(mirror_keys, key); | |
148 | CFRelease(key); | |
149 | ||
150 | // Setup:/System | |
151 | // key = SCDynamicStoreKeyCreateComputerName(NULL); | |
152 | // CFArrayAppendValue(mirror_keys, key); | |
153 | // CFRelease(key); | |
154 | ||
155 | // Setup:/Network | |
156 | // key = SCDynamicStoreKeyCreateHostNames(NULL); | |
157 | // CFArrayAppendValue(mirror_keys, key); | |
158 | // CFRelease(key); | |
159 | ||
160 | // Setup:/Network/Global/.* | |
161 | pattern = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, | |
162 | kSCDynamicStoreDomainSetup, | |
163 | kSCCompAnyRegex); | |
164 | CFArrayAppendValue(mirror_patterns, pattern); | |
165 | CFRelease(pattern); | |
166 | ||
167 | // Setup:/Network/Service/.* | |
168 | // State:/Network/Service/.* | |
169 | pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, | |
170 | kSCCompAnyRegex, | |
171 | CFSTR(".*"), | |
172 | NULL); | |
173 | CFArrayAppendValue(mirror_patterns, pattern); | |
174 | CFRelease(pattern); | |
175 | ||
176 | // Setup:/Network/Interface/.* | |
177 | // State:/Network/Interface/.* | |
178 | pattern = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, | |
179 | kSCCompAnyRegex, | |
180 | CFSTR(".*"), | |
181 | NULL); | |
182 | CFArrayAppendValue(mirror_patterns, pattern); | |
183 | CFRelease(pattern); | |
184 | ||
185 | // State:/Network/MulticastDNS | |
186 | key = SCDynamicStoreKeyCreate(NULL, CFSTR("%@/%@/%@"), | |
187 | kSCDynamicStoreDomainState, | |
188 | kSCCompNetwork, | |
189 | CFSTR(kDNSServiceCompMulticastDNS)); | |
190 | CFArrayAppendValue(mirror_keys, key); | |
191 | CFRelease(key); | |
192 | ||
193 | // State:/Network/PrivateDNS | |
194 | key = SCDynamicStoreKeyCreate(NULL, CFSTR("%@/%@/%@"), | |
195 | kSCDynamicStoreDomainState, | |
196 | kSCCompNetwork, | |
197 | CFSTR(kDNSServiceCompPrivateDNS)); | |
198 | CFArrayAppendValue(mirror_keys, key); | |
199 | CFRelease(key); | |
200 | ||
201 | return; | |
202 | } | |
203 | ||
204 | ||
205 | #define N_QUICK 64 | |
206 | ||
207 | ||
208 | __private_extern__ | |
209 | void | |
210 | prime_SimulatorSupport() | |
211 | { | |
212 | CFDictionaryRef content_host; | |
213 | CFIndex n; | |
214 | ||
9de8ab86 | 215 | SC_log(LOG_DEBUG, "prime() called"); |
5e9ce69e A |
216 | |
217 | // copy current content from base OS store to _Sim store | |
218 | content_host = SCDynamicStoreCopyMultiple(store_host, mirror_keys, mirror_patterns); | |
219 | CFRelease(mirror_keys); | |
220 | mirror_keys = NULL; | |
221 | CFRelease(mirror_patterns); | |
222 | mirror_patterns = NULL; | |
223 | ||
224 | if (content_host == NULL) { | |
225 | return; | |
226 | } | |
227 | ||
228 | n = CFDictionaryGetCount(content_host); | |
229 | if (n > 0) { | |
230 | CFArrayRef changes; | |
231 | const void * keys_host_q[N_QUICK]; | |
232 | const void ** keys_host = keys_host_q; | |
233 | ||
234 | if (n > (CFIndex)(sizeof(keys_host_q) / sizeof(CFStringRef))) { | |
235 | keys_host = CFAllocatorAllocate(NULL, n * sizeof(CFStringRef), 0); | |
236 | } | |
237 | ||
238 | CFDictionaryGetKeysAndValues(content_host, keys_host, NULL); | |
239 | ||
240 | changes = CFArrayCreate(NULL, keys_host, n, &kCFTypeArrayCallBacks); | |
241 | mirror(store_host, changes, (void *)content_host); | |
242 | CFRelease(changes); | |
243 | ||
244 | if (keys_host != keys_host_q) { | |
245 | CFAllocatorDeallocate(NULL, keys_host); | |
246 | } | |
247 | } | |
248 | ||
249 | CFRelease(content_host); | |
250 | return; | |
251 | } | |
252 | ||
253 | ||
254 | __private_extern__ | |
255 | void | |
256 | load_SimulatorSupport(CFBundleRef bundle, Boolean bundleVerbose) | |
257 | { | |
258 | Boolean ok; | |
259 | CFMutableDictionaryRef options; | |
260 | CFRunLoopSourceRef rls; | |
261 | ||
9de8ab86 A |
262 | SC_log(LOG_DEBUG, "load() called"); |
263 | SC_log(LOG_DEBUG, " bundle ID = %@", CFBundleGetIdentifier(bundle)); | |
5e9ce69e A |
264 | |
265 | // setup | |
266 | mirror_setup(); | |
267 | ||
268 | // setup SCDynamicStore mirroring (from "host") | |
269 | options = CFDictionaryCreateMutable(NULL, | |
270 | 0, | |
271 | &kCFTypeDictionaryKeyCallBacks, | |
272 | &kCFTypeDictionaryValueCallBacks); | |
273 | CFDictionarySetValue(options, kSCDynamicStoreUseHostServer, kCFBooleanTrue); | |
274 | store_host = SCDynamicStoreCreateWithOptions(NULL, | |
275 | CFSTR("SimulatorSupport(host)"), | |
276 | options, | |
277 | mirror, | |
278 | NULL); | |
279 | CFRelease(options); | |
280 | assert(store_host != NULL); | |
281 | ||
282 | ok = SCDynamicStoreSetNotificationKeys(store_host, mirror_keys, mirror_patterns); | |
283 | assert(ok); | |
284 | ||
285 | rls = SCDynamicStoreCreateRunLoopSource(NULL, store_host, 0); | |
286 | assert(rls != NULL); | |
287 | ||
288 | CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); | |
289 | CFRelease(rls); | |
290 | ||
291 | // setup SCDynamicStore mirroring (to "iOS Simulator") | |
292 | store_sim = SCDynamicStoreCreate(NULL, | |
293 | CFSTR("SimulatorSupport(sim)"), | |
294 | NULL, | |
295 | NULL); | |
296 | ||
297 | return; | |
298 | } | |
299 | ||
300 | ||
301 | #ifdef MAIN | |
302 | ||
303 | ||
304 | #pragma mark - | |
305 | #pragma mark Standalone test code | |
306 | ||
307 | ||
308 | int | |
309 | main(int argc, char **argv) | |
310 | { | |
311 | _sc_log = FALSE; | |
312 | _sc_verbose = (argc > 1) ? TRUE : FALSE; | |
313 | ||
314 | load_SimulatorSupport(CFBundleGetMainBundle(), (argc > 1) ? TRUE : FALSE); | |
315 | prime_SimulatorSupport(); | |
316 | CFRunLoopRun(); | |
317 | // not reached | |
318 | exit(0); | |
319 | return 0; | |
320 | } | |
321 | #endif |