]> git.saurik.com Git - apple/configd.git/blob - SystemConfiguration.fproj/SCNetworkMigration.c
configd-1061.141.1.tar.gz
[apple/configd.git] / SystemConfiguration.fproj / SCNetworkMigration.c
1 /*
2 * Copyright (c) 2014-2020 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 // SCNetworkMigration.c
26 //
27 // Created by Ashish Kulkarni on 11/19/13.
28 //
29 //
30
31 #include <stdio.h>
32 #include <CoreFoundation/CoreFoundation.h>
33 #include "SCNetworkConfigurationInternal.h"
34 #include "SCPreferencesInternal.h"
35 #include <IOKit/network/IONetworkInterface.h>
36 #include <IOKit/network/IONetworkController.h>
37 #include <sys/stat.h>
38 #include <copyfile.h>
39 #include <sys/param.h>
40 #include <pthread.h>
41
42 #define BACK_TO_MY_MAC CFSTR("BackToMyMac")
43 #define BACK_TO_MY_MAC_DSIDS CFSTR("BackToMyMacDSIDs")
44 #define NUM_MIGRATION_PATHS 2
45 #define PLUGIN_ID CFSTR("System Migration")
46 #define PREFERENCES_PLIST_INDEX 0
47 #define NETWORK_INTERFACES_PLIST_INDEX 1
48
49 #define kProtocolType CFSTR("Protocol Type")
50 #define kProtocolConfiguration CFSTR("Protocol Configuration")
51 #define kProtocolEnabled CFSTR("Protocol Enabled")
52
53
54 const CFStringRef kSCNetworkConfigurationMigrationActionKey = CFSTR("MigrationActionKey");
55 const CFStringRef kSCNetworkConfigurationRepair = CFSTR("ConfigurationRepair");
56
57 #if !TARGET_OS_IPHONE
58 static CFDictionaryRef
59 _SCNetworkMigrationCopyMappingBSDNameToBridgeServices(SCPreferencesRef prefs);
60
61 static CFDictionaryRef
62 _SCNetworkMigrationCopyMappingBSDNameToBondServices(SCPreferencesRef prefs);
63
64 static CFDictionaryRef
65 _SCNetworkMigrationCopyMappingBSDNameToVLANServices(SCPreferencesRef prefs);
66 #endif // !TARGET_OS_IPHONE
67
68 static Boolean
69 _SCNetworkConfigurationIsInterfaceNamerMappable(SCNetworkInterfaceRef interface1, SCNetworkInterfaceRef interface2, Boolean bypassActive);
70
71 static Boolean
72 _SCNetworkConfigurationMigrateConfiguration(CFURLRef sourceDir, CFURLRef targetDir);
73
74 static void
75 _SCNetworkConfigurationCopyMigrationPathsWithBaseURL(CFURLRef baseURL, CFURLRef *prefs, CFURLRef *interfaces)
76 {
77 if (baseURL != NULL) {
78 CFRetain(baseURL);
79 } else {
80 baseURL = CFURLCreateFromFileSystemRepresentation(NULL,
81 (UInt8*)PREFS_DEFAULT_DIR_PATH,
82 sizeof(PREFS_DEFAULT_DIR_PATH) - 1,
83 TRUE);
84 }
85
86 *prefs = CFURLCreateFromFileSystemRepresentationRelativeToBase(NULL,
87 (UInt8*)PREFS_DEFAULT_CONFIG_PLIST,
88 sizeof(PREFS_DEFAULT_CONFIG_PLIST) - 1,
89 FALSE,
90 baseURL);
91
92 *interfaces = CFURLCreateFromFileSystemRepresentationRelativeToBase(NULL,
93 (UInt8*)INTERFACES_DEFAULT_CONFIG_PLIST,
94 sizeof(INTERFACES_DEFAULT_CONFIG_PLIST) - 1,
95 FALSE,
96 baseURL);
97 CFRelease(baseURL);
98 return;
99 }
100
101 CFArrayRef
102 _SCNetworkConfigurationCopyMigrationPaths(CFDictionaryRef options)
103 {
104 #pragma unused(options)
105 CFURLRef interfaces;
106 CFMutableArrayRef migrationPaths = NULL;
107 CFURLRef prefs;
108
109 migrationPaths = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
110 _SCNetworkConfigurationCopyMigrationPathsWithBaseURL(NULL, &prefs, &interfaces);
111 CFArrayAppendValue(migrationPaths, prefs);
112 CFArrayAppendValue(migrationPaths, interfaces);
113 CFRelease(prefs);
114 CFRelease(interfaces);
115
116 SC_log(LOG_INFO,
117 "_SCNetworkConfigurationCopyMigrationPaths() called%s"
118 "\n options = %@"
119 "\n paths = %@",
120 _SC_isInstallEnvironment() ? " (INSTALLER ENVIRONMENT)" : "",
121 options,
122 migrationPaths);
123
124 return migrationPaths;
125 }
126
127 static Boolean
128 _SCNetworkConfigurationRemoveConfigurationFiles(CFURLRef configDir)
129 {
130
131 char configPathString[PATH_MAX];
132 CFURLRef configPathURL = NULL;
133 char configNetworkInterfacesPathString[PATH_MAX];
134 CFURLRef configNetworkInterfacesPathURL = NULL;
135
136 _SCNetworkConfigurationCopyMigrationPathsWithBaseURL(configDir, &configPathURL, &configNetworkInterfacesPathURL);
137
138 if(!CFURLGetFileSystemRepresentation(configPathURL,
139 TRUE,
140 (UInt8*)configPathString,
141 sizeof(configPathString))) {
142 SC_log(LOG_NOTICE, "Cannot get file system representation for url: %@", configPathURL);
143 } else {
144 if ((remove(configPathString) != 0) && (errno != ENOENT)) {
145 SC_log(LOG_NOTICE, "remove(\"%s\") failed: %s", configPathString, strerror(errno));
146 }
147 }
148 CFRelease(configPathURL);
149
150 if(!CFURLGetFileSystemRepresentation(configNetworkInterfacesPathURL,
151 TRUE,
152 (UInt8*)configNetworkInterfacesPathString,
153 sizeof(configNetworkInterfacesPathString))) {
154 SC_log(LOG_NOTICE, "Cannot get file system representation for url: %@", configNetworkInterfacesPathURL);
155 } else {
156 if ((remove(configNetworkInterfacesPathString) != 0) && (errno != ENOENT)) {
157 SC_log(LOG_NOTICE, "remove(\"%s\") failed: %s", configNetworkInterfacesPathString, strerror(errno));
158 }
159 }
160 CFRelease(configNetworkInterfacesPathURL);
161
162 return TRUE;
163 }
164
165 static Boolean
166 SCNetworkConfigurationCopyConfigurationFiles(CFURLRef configDir,
167 CFURLRef targetDir) // TargetDir needs to exist
168 {
169 errno_t error;
170 mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
171 char networkInterfacesPathString[PATH_MAX];
172 CFURLRef networkInterfacesPathURL = NULL;
173 copyfile_state_t networkInterfacesState;
174 char preferencesPathString[PATH_MAX];
175 CFURLRef preferencesPathURL = NULL;
176 Boolean removeTargetFiles = FALSE;
177 copyfile_state_t state;
178 Boolean success = FALSE;
179 char targetNetworkInterfacesPathString[PATH_MAX];
180 CFURLRef targetNetworkInterfacesPathURL = NULL;
181 char targetPathString[PATH_MAX];
182 CFURLRef targetPathURL = NULL;
183
184 _SCNetworkConfigurationCopyMigrationPathsWithBaseURL(targetDir, &targetPathURL, &targetNetworkInterfacesPathURL);
185
186 if (!CFURLGetFileSystemRepresentation(targetPathURL,
187 TRUE,
188 (UInt8*)targetPathString,
189 sizeof(targetPathString))) {
190 SC_log(LOG_NOTICE, "Cannot get file system representation for url: %@", targetPathURL);
191 goto done;
192 }
193 if (!CFURLGetFileSystemRepresentation(targetNetworkInterfacesPathURL,
194 TRUE,
195 (UInt8*)targetNetworkInterfacesPathString,
196 sizeof(targetNetworkInterfacesPathString))) {
197 SC_log(LOG_NOTICE, "Cannot get file system representation for url: %@", targetNetworkInterfacesPathURL);
198 goto done;
199 }
200
201 if (configDir == NULL) {
202 removeTargetFiles = TRUE;
203 success = TRUE;
204 goto done;
205 }
206
207 _SCNetworkConfigurationCopyMigrationPathsWithBaseURL(configDir, &preferencesPathURL, &networkInterfacesPathURL);
208
209 if (!CFURLGetFileSystemRepresentation(preferencesPathURL,
210 TRUE,
211 (UInt8*)preferencesPathString,
212 sizeof(preferencesPathString))) {
213 SC_log(LOG_NOTICE, "Cannot get file system representation for url: %@", preferencesPathURL);
214 goto done;
215 }
216 if (!CFURLGetFileSystemRepresentation(networkInterfacesPathURL,
217 TRUE,
218 (UInt8*)networkInterfacesPathString,
219 sizeof(networkInterfacesPathString))) {
220 SC_log(LOG_NOTICE, "Cannot get file system representation for url: %@", networkInterfacesPathURL);
221 goto done;
222 }
223
224 state = copyfile_state_alloc();
225 error = copyfile(preferencesPathString, targetPathString, state, COPYFILE_ALL);
226 if (error != 0) {
227 SC_log(LOG_NOTICE, "copyFile(\"%s\", \"%s\", ...) failed: %s",
228 preferencesPathString,
229 targetPathString,
230 strerror(errno));
231 copyfile_state_free(state);
232 removeTargetFiles = TRUE;
233 goto done;
234 }
235 copyfile_state_free(state);
236 (void)chmod(targetPathString, mode);
237
238 networkInterfacesState = copyfile_state_alloc();
239 error = copyfile(networkInterfacesPathString, targetNetworkInterfacesPathString, networkInterfacesState, COPYFILE_ALL);
240 if (error != 0) {
241 SC_log(LOG_NOTICE, "copyFile(\"%s\", \"%s\", ...) failed: %s",
242 networkInterfacesPathString,
243 targetNetworkInterfacesPathString,
244 strerror(errno));
245 copyfile_state_free(networkInterfacesState);
246 removeTargetFiles = TRUE;
247 goto done;
248 }
249 copyfile_state_free(networkInterfacesState);
250 (void)chmod(targetNetworkInterfacesPathString, mode);
251
252 success = TRUE;
253 done:
254 if (removeTargetFiles) {
255 _SCNetworkConfigurationRemoveConfigurationFiles(targetDir);
256 }
257 if (preferencesPathURL != NULL) {
258 CFRelease(preferencesPathURL);
259 }
260 if (networkInterfacesPathURL != NULL) {
261 CFRelease(networkInterfacesPathURL);
262 }
263 if (targetPathURL != NULL) {
264 CFRelease(targetPathURL);
265 }
266 if (targetNetworkInterfacesPathURL != NULL) {
267 CFRelease(targetNetworkInterfacesPathURL);
268 }
269 return success;
270 }
271
272
273 /* -----------------------------------------------------------------------------
274 Create directories and intermediate directories as required.
275 ----------------------------------------------------------------------------- */
276 static Boolean
277 _SCNetworkConfigurationMakePathIfNeeded(CFURLRef pathURL)
278 {
279 char *c;
280 char path[PATH_MAX];
281 Boolean success = FALSE;
282
283 if (!CFURLGetFileSystemRepresentation(pathURL, TRUE, (UInt8 *)path, sizeof(path))) {
284 SC_log(LOG_NOTICE, "Cannot get file system representation for url: %@", pathURL);
285 return success;
286 }
287
288 SC_log(LOG_INFO, "creating path: %s", path);
289
290 c = path;
291 if (*c == '/') {
292 c++; // skip leading /
293 }
294 for(; !success; c++) {
295 if ((*c == '/') || (*c == '\0')){
296 if (*c == '\0') {
297 success = TRUE;
298 } else {
299 *c = '\0';
300 }
301 if (mkdir(path, (S_IRWXU | S_IRGRP | S_IROTH | S_IXGRP | S_IXOTH)) != 0) {
302 if ((errno != EEXIST) && (errno != EISDIR)) {
303 SC_log(LOG_NOTICE, "mkdir(%s) failed: %s", path, strerror(errno));
304 break;
305 }
306 }
307 *c = '/';
308 }
309 }
310
311 return success;
312 }
313
314 static void
315 __SCNetworkPopulateDefaultPrefs(SCPreferencesRef prefs)
316 {
317 SCNetworkSetRef currentSet;
318 CFStringRef model;
319 CFNumberRef version;
320
321 SC_log(LOG_INFO,
322 "Populating preferences.plist"
323 "\n %@",
324 prefs);
325
326 currentSet = SCNetworkSetCopyCurrent(prefs);
327 if (currentSet == NULL) {
328 currentSet = _SCNetworkSetCreateDefault(prefs);
329 }
330 SCNetworkSetEstablishDefaultConfiguration(currentSet);
331 CFRelease(currentSet);
332
333 model = SCPreferencesGetValue(prefs, MODEL);
334 if (model == NULL) {
335 model = _SC_hw_model(FALSE);
336 SCPreferencesSetValue(prefs, MODEL, model);
337 }
338
339 version = SCPreferencesGetValue(prefs, kSCPrefVersion);
340 if (version == NULL) {
341 const int new_version = NETWORK_CONFIGURATION_VERSION;
342
343 version = CFNumberCreate(NULL, kCFNumberIntType, &new_version);
344 SCPreferencesSetValue(prefs, kSCPrefVersion, version);
345 CFRelease(version);
346 }
347
348 return;
349 }
350
351 __private_extern__
352 void
353 __SCNetworkPopulateDefaultNIPrefs(SCPreferencesRef ni_prefs)
354 {
355 CFMutableArrayRef interfaces = NULL;
356 CFStringRef model;
357 CFArrayRef networkInterfaces;
358 CFComparisonResult res;
359 CFNumberRef version;
360
361 interfaces = (CFMutableArrayRef)SCPreferencesGetValue(ni_prefs, INTERFACES);
362 if (isA_CFArray(interfaces)) {
363 // if already populated
364 return;
365 }
366
367 SC_log(LOG_INFO,
368 "Populating NetworkInterfaces.plist"
369 "\n %@",
370 ni_prefs);
371
372 networkInterfaces = __SCNetworkInterfaceCopyAll_IONetworkInterface(TRUE);
373 if (networkInterfaces == NULL) {
374 SC_log(LOG_NOTICE, "Cannot populate NetworkInterfaces.plist, no network interfaces");
375 return;
376 }
377
378 interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
379
380 for (CFIndex idx = 0; idx < CFArrayGetCount(networkInterfaces); idx++) {
381 CFIndex idx2 = 0;
382 CFNumberRef if_type;
383 CFNumberRef if_unit;
384 SCNetworkInterfaceRef interface = CFArrayGetValueAtIndex(networkInterfaces, idx);
385 CFDictionaryRef interfaceEntity;
386
387 interfaceEntity = __SCNetworkInterfaceCopyStorageEntity(interface);
388 if (interfaceEntity == NULL) {
389 continue;
390 }
391
392 if_type = _SCNetworkInterfaceGetIOInterfaceType(interface);
393 if_unit = _SCNetworkInterfaceGetIOInterfaceUnit(interface);
394 if ((if_type == NULL) || (if_unit == NULL)) {
395 CFRelease(interfaceEntity);
396 continue;
397 }
398
399 for (idx2 = 0; idx2 < CFArrayGetCount(interfaces); idx2++) {
400 CFNumberRef db_type;
401 CFNumberRef db_unit;
402 CFDictionaryRef dict = CFArrayGetValueAtIndex(interfaces, idx2);
403
404 db_type = CFDictionaryGetValue(dict, CFSTR(kIOInterfaceType));
405 db_unit = CFDictionaryGetValue(dict, CFSTR(kIOInterfaceUnit));
406 res = CFNumberCompare(if_type, db_type, NULL);
407 if (res == kCFCompareLessThan
408 || (res == kCFCompareEqualTo
409 && (CFNumberCompare(if_unit, db_unit, NULL) == kCFCompareLessThan))) {
410 break;
411 }
412 }
413
414 CFArrayInsertValueAtIndex(interfaces, idx2, interfaceEntity);
415 CFRelease(interfaceEntity);
416
417 }
418
419 SCPreferencesSetValue(ni_prefs, INTERFACES, interfaces);
420 CFRelease(interfaces);
421
422 model = SCPreferencesGetValue(ni_prefs, MODEL);
423 if (model == NULL) {
424 model = _SC_hw_model(FALSE);
425 SCPreferencesSetValue(ni_prefs, MODEL, model);
426 }
427
428 version = SCPreferencesGetValue(ni_prefs, kSCPrefVersion);
429 if (version == NULL) {
430 const int new_version = NETWORK_CONFIGURATION_VERSION;
431
432 version = CFNumberCreate(NULL, kCFNumberIntType, &new_version);
433 SCPreferencesSetValue(ni_prefs, kSCPrefVersion, version);
434 CFRelease(version);
435 }
436
437 CFRelease(networkInterfaces);
438
439 return;
440 }
441
442
443 /*
444 * _SCNetworkConfigurationPerformMigration will migrate configuration between source and destination systems
445 */
446 CF_RETURNS_RETAINED
447 CFArrayRef
448 _SCNetworkConfigurationPerformMigration(CFURLRef sourceDir, CFURLRef currentDir, CFURLRef targetDir, CFDictionaryRef options)
449 {
450 #pragma unused(options)
451 CFURLRef currentDirConfig = NULL;
452 CFURLRef currentSystemPath = NULL;
453 Boolean migrationComplete = FALSE;
454 CFArrayRef paths = NULL;
455 Boolean removeTargetOnFailure = FALSE;
456 CFURLRef sourceDirConfig = NULL;
457 CFURLRef targetDirConfig = NULL;
458
459 SC_log(LOG_INFO,
460 "_SCNetworkConfigurationPerformMigration() called%s"
461 "\n sourceDir = %@"
462 "\n currentDir = %@"
463 "\n targetDir = %@"
464 "\n options = %@",
465 _SC_isInstallEnvironment() ? " (INSTALLER ENVIRONMENT)" : "",
466 sourceDir,
467 currentDir,
468 targetDir,
469 options);
470
471 if ((sourceDir != NULL) && !CFURLHasDirectoryPath(sourceDir)) {
472 SC_log(LOG_NOTICE, "Migration source is not a directory: %@", sourceDir);
473 goto done;
474 }
475
476 if ((currentDir != NULL) && !CFURLHasDirectoryPath(currentDir)) {
477 SC_log(LOG_NOTICE, "Migration current is not a directory: %@", currentDir);
478 goto done;
479 }
480
481 if ((targetDir != NULL) && !CFURLHasDirectoryPath(targetDir)) {
482 SC_log(LOG_NOTICE, "Migration target is not a directory: %@", targetDir);
483 goto done;
484 }
485
486 // Both sourceDir and currentDir cannot be NULL because NULL value indicates using current system
487 if (sourceDir == NULL && currentDir == NULL) {
488 SC_log(LOG_NOTICE, "Both migration source and current are NULL");
489 goto done;
490 }
491
492 currentSystemPath = CFURLCreateWithString(NULL,
493 PREFS_DEFAULT_DIR,
494 NULL);
495
496 // if either of the sourceDir or currentDir are NULL, then populate it with current system path
497 if (sourceDir == NULL) {
498 sourceDirConfig = CFRetain(currentSystemPath);
499 } else {
500 sourceDirConfig = CFURLCreateWithFileSystemPathRelativeToBase(NULL,
501 PREFS_DEFAULT_DIR_RELATIVE,
502 kCFURLPOSIXPathStyle,
503 TRUE,
504 sourceDir);
505 }
506
507 if (currentDir != NULL) {
508 currentDirConfig = CFURLCreateWithFileSystemPathRelativeToBase(NULL,
509 PREFS_DEFAULT_DIR_RELATIVE,
510 kCFURLPOSIXPathStyle,
511 TRUE,
512 currentDir);
513 }
514 // If the targetDir is not provided then migration will take place in currentDir
515 if (targetDir == NULL) {
516 targetDirConfig = CFRetain(currentSystemPath);
517 } else {
518 targetDirConfig = CFURLCreateWithFileSystemPathRelativeToBase(NULL,
519 PREFS_DEFAULT_DIR_RELATIVE,
520 kCFURLPOSIXPathStyle,
521 TRUE,
522 targetDir);
523 }
524 // Source directory cannot be the same as target directory
525 if (CFEqual(sourceDirConfig, targetDirConfig)) {
526 SC_log(LOG_NOTICE, "Source directory cannot be the same as target directory");
527 goto done;
528 }
529
530 if ((currentDirConfig == NULL) || !CFEqual(currentDirConfig, targetDirConfig)) {
531 if (!_SCNetworkConfigurationMakePathIfNeeded(targetDirConfig)) {
532 SC_log(LOG_NOTICE, "Could not create target directory");
533 goto done;
534 }
535
536 if (!SCNetworkConfigurationCopyConfigurationFiles(currentDirConfig, targetDirConfig)) {
537 SC_log(LOG_NOTICE, "Could not copy configuration files from \"%@\" to \"%@\"",
538 currentDirConfig,
539 targetDirConfig);
540 } else if (currentDirConfig != NULL) {
541 removeTargetOnFailure = TRUE; // Configuration files were copied over to target directory
542 // If migration failed, then we should remove those configuration
543 // files since current directory and target directory are not
544 // the same
545 }
546 }
547
548 // If both source and current configurations point to current system, then no migration needs to be done.
549 if ((currentDirConfig != NULL) && CFEqual(sourceDirConfig, currentDirConfig)) {
550 SC_log(LOG_NOTICE, "No migration needed, source and current configurations have the same path");
551 migrationComplete = TRUE;
552 } else {
553 migrationComplete = _SCNetworkConfigurationMigrateConfiguration(sourceDirConfig, targetDirConfig);
554 }
555 if (migrationComplete) {
556 SC_log(LOG_NOTICE, "Migration complete");
557 paths = _SCNetworkConfigurationCopyMigrationPaths(NULL);
558 } else {
559 SC_log(LOG_NOTICE, "Migration failed: %s", SCErrorString(SCError()));
560
561 // If migration fails, then remove configuration files from target config if they were
562 // copied from the current directory
563 if (removeTargetOnFailure) {
564 _SCNetworkConfigurationRemoveConfigurationFiles(targetDirConfig);
565 }
566 }
567 done:
568 if (currentDirConfig != NULL) {
569 CFRelease(currentDirConfig);
570 }
571 if (currentSystemPath != NULL) {
572 CFRelease(currentSystemPath);
573 }
574 if (sourceDirConfig != NULL) {
575 CFRelease(sourceDirConfig);
576 }
577 if (targetDirConfig != NULL) {
578 CFRelease(targetDirConfig);
579 }
580
581 return paths;
582 }
583
584 static Boolean
585 _SCNetworkConfigurationMigrateIsFilePresent(CFURLRef filePath)
586 {
587 Boolean fileExists = false;
588 char filePathStr[PATH_MAX];
589 int statResult = 0;
590 struct stat statStruct = {0, };
591
592 if (filePath == NULL) {
593 SC_log(LOG_NOTICE, "_SCNetworkConfigurationMigrateIsFilePresent: No path");
594 goto done;
595 }
596
597 if (!CFURLGetFileSystemRepresentation(filePath, TRUE, (UInt8*) filePathStr, sizeof(filePathStr))) {
598 SC_log(LOG_NOTICE, "Cannot get file system representation for url: %@", filePath);
599 goto done;
600 }
601
602 statResult = stat(filePathStr, &statStruct);
603 if (statResult == 0) {
604 SCPreferencesRef prefs;
605 CFStringRef prefsID;
606
607 if (statStruct.st_size == 0) {
608 SC_log(LOG_INFO, "_SCNetworkConfigurationMigrateIsFilePresent: empty .plist: %@", filePath); // REMOVE
609 goto done;
610 }
611
612 prefsID = CFStringCreateWithCString(NULL, filePathStr, kCFStringEncodingUTF8);
613 prefs = SCPreferencesCreate(NULL, PLUGIN_ID, prefsID);
614 CFRelease(prefsID);
615 if (prefs == NULL) {
616 SC_log(LOG_NOTICE, "_SCNetworkConfigurationMigrateIsFilePresent: bad .plist: %@", filePath);
617 goto done;
618 }
619
620 if (!__SCPreferencesIsEmpty(prefs)) {
621 // if non-empty .plist
622 fileExists = TRUE;
623 } else {
624 SC_log(LOG_NOTICE, "_SCNetworkConfigurationMigrateIsFilePresent: effectively empty .plist: %@", filePath);
625 }
626
627 CFRelease(prefs);
628 }
629 done:
630 return fileExists;
631 }
632
633 static Boolean
634 __SCNetworkConfigurationMigrateConfigurationFilesPresent(CFURLRef baseURL, CFArrayRef* migrationPaths, Boolean expected)
635 {
636 Boolean configFilesPresent = FALSE;
637 CFIndex count;
638 CFURLRef filePath = NULL;
639 CFURLRef interfaces;
640 CFMutableArrayRef migrationPathsMutable = NULL;
641 CFURLRef prefs;
642
643 if (baseURL == NULL) {
644 SC_log(LOG_NOTICE, "No base migration URL");
645 goto done;
646 }
647
648 migrationPathsMutable = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
649 _SCNetworkConfigurationCopyMigrationPathsWithBaseURL(baseURL, &prefs, &interfaces);
650 CFArrayAppendValue(migrationPathsMutable, prefs);
651 CFArrayAppendValue(migrationPathsMutable, interfaces);
652 CFRelease(prefs);
653 CFRelease(interfaces);
654
655 *migrationPaths = migrationPathsMutable;
656
657 count = CFArrayGetCount(*migrationPaths);
658 for (CFIndex idx = 0; idx < count; idx++) {
659 Boolean present;
660
661 filePath = CFArrayGetValueAtIndex(*migrationPaths, idx);
662 present = _SCNetworkConfigurationMigrateIsFilePresent(filePath);
663 if (!present) {
664 if (expected) {
665 SC_log(LOG_INFO, "Expected migration file not present: %@", filePath);
666 }
667 goto done;
668 }
669 }
670
671 configFilesPresent = TRUE; // all necessary configuration files present
672 done:
673 return configFilesPresent;
674 }
675
676
677 static CFMutableArrayRef
678 _SCNetworkInterfaceCopyInterfacesFilteredByBuiltinWithPreferences(SCPreferencesRef ni_prefs, Boolean isBuiltin)
679 {
680 CFIndex count = 0;
681 SCNetworkInterfaceRef interface;
682 CFArrayRef interfaceList = NULL;
683 CFMutableArrayRef resultInterfaceList = NULL;
684
685 interfaceList = __SCNetworkInterfaceCopyStoredWithPreferences(ni_prefs);
686 if (interfaceList == NULL) {
687 goto done;
688 }
689
690 count = CFArrayGetCount(interfaceList);
691 if (count > 0) {
692 resultInterfaceList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
693 }
694
695 for (CFIndex i = 0; i < count; i++) {
696 interface = CFArrayGetValueAtIndex(interfaceList, i);
697
698 if (_SCNetworkInterfaceIsBuiltin(interface) == isBuiltin) {
699 CFArrayAppendValue(resultInterfaceList, interface);
700 }
701 }
702
703 done:
704 if (interfaceList != NULL) {
705 CFRelease(interfaceList);
706 }
707 return resultInterfaceList;
708 }
709
710 static CFMutableDictionaryRef
711 _SCNetworkInterfaceStorageCopyMaxUnitPerInterfaceType(SCPreferencesRef ni_prefs)
712 {
713 CFNumberRef cfMaxUnit;
714 CFIndex count = 0;
715 CFArrayRef ifList = NULL;
716 SCNetworkInterfaceRef interface;
717 CFMutableDictionaryRef interfaceTypeToMaxUnitMapping = NULL;
718 CFNumberRef type;
719 CFNumberRef unit;
720
721 ifList = __SCNetworkInterfaceCopyStoredWithPreferences(ni_prefs);
722 if (ifList == NULL) {
723 SC_log(LOG_INFO, "No interfaces");
724 return NULL;
725 }
726
727 interfaceTypeToMaxUnitMapping = CFDictionaryCreateMutable(NULL, 0,
728 &kCFTypeDictionaryKeyCallBacks,
729 &kCFTypeDictionaryValueCallBacks);
730 count = CFArrayGetCount(ifList);
731 for (CFIndex idx = 0; idx < count; idx++) {
732 cfMaxUnit = NULL;
733 interface = CFArrayGetValueAtIndex(ifList, idx);
734
735 if (!isA_SCNetworkInterface(interface)) {
736 continue;
737 }
738
739 type = _SCNetworkInterfaceGetIOInterfaceType(interface);
740 if (!isA_CFNumber(type)) {
741 SC_log(LOG_INFO, "No interface type");
742 continue;
743 }
744
745 if (!CFDictionaryContainsKey(interfaceTypeToMaxUnitMapping, type)) {
746 int temp = 0;
747 cfMaxUnit = CFNumberCreate(NULL, kCFNumberIntType, &temp);
748 CFDictionaryAddValue(interfaceTypeToMaxUnitMapping, type, cfMaxUnit);
749 CFRelease(cfMaxUnit);
750 }
751
752 if (cfMaxUnit == NULL) {
753 cfMaxUnit = CFDictionaryGetValue(interfaceTypeToMaxUnitMapping, type);
754 }
755
756 unit = _SCNetworkInterfaceGetIOInterfaceUnit(interface);
757 if (!isA_CFNumber(unit)) {
758 continue;
759 }
760
761 if (CFNumberCompare(unit, cfMaxUnit, NULL) == kCFCompareGreaterThan) {
762 CFDictionarySetValue(interfaceTypeToMaxUnitMapping, type, unit);
763 }
764 }
765 if (ifList != NULL) {
766 CFRelease(ifList);
767 }
768 return interfaceTypeToMaxUnitMapping;
769 }
770
771 static CFMutableDictionaryRef
772 _SCNetworkConfigurationCopyBuiltinMapping (SCPreferencesRef sourcePrefs, SCPreferencesRef targetPrefs)
773 {
774 CFMutableDictionaryRef builtinMapping = NULL;
775 CFIndex sourceBuiltinInterfaceCount = 0;
776 CFMutableArrayRef sourceBuiltinInterfaces = NULL;
777 SCNetworkInterfaceRef sourceInterface;
778 CFIndex targetBuiltinInterfaceCount = 0;
779 CFMutableArrayRef targetBuiltinInterfaces = NULL;
780 SCNetworkInterfaceRef targetInterface;
781
782 sourceBuiltinInterfaces = _SCNetworkInterfaceCopyInterfacesFilteredByBuiltinWithPreferences(sourcePrefs, TRUE);
783 if (!isA_CFArray(sourceBuiltinInterfaces)) {
784 SC_log(LOG_INFO, "No source built-in interfaces");
785 goto done;
786 }
787 sourceBuiltinInterfaceCount = CFArrayGetCount(sourceBuiltinInterfaces);
788
789 targetBuiltinInterfaces = _SCNetworkInterfaceCopyInterfacesFilteredByBuiltinWithPreferences(targetPrefs, TRUE);
790 if (!isA_CFArray(targetBuiltinInterfaces)) {
791 SC_log(LOG_INFO, "No target built-in interfaces");
792 goto done;
793 }
794
795 // Builtin Mapping will try to map all source interfaces into target interfaces
796 for (CFIndex idx = 0; idx < sourceBuiltinInterfaceCount; idx++) {
797 Boolean matched = FALSE;
798
799 sourceInterface = CFArrayGetValueAtIndex(sourceBuiltinInterfaces, idx);
800 targetBuiltinInterfaceCount = CFArrayGetCount(targetBuiltinInterfaces);
801
802 for (CFIndex idx2 = 0; idx2 < targetBuiltinInterfaceCount; idx2++) {
803 CFDataRef sourceHardwareAddress;
804 CFDataRef targetHardwareAddress;
805
806 targetInterface = CFArrayGetValueAtIndex(targetBuiltinInterfaces, idx2);
807 sourceHardwareAddress = _SCNetworkInterfaceGetHardwareAddress(sourceInterface);
808 targetHardwareAddress = _SCNetworkInterfaceGetHardwareAddress(targetInterface);
809 if (_SC_CFEqual(sourceHardwareAddress, targetHardwareAddress)) {
810 if (builtinMapping == NULL) {
811 builtinMapping = CFDictionaryCreateMutable(NULL, 0,
812 &kCFTypeDictionaryKeyCallBacks,
813 &kCFTypeDictionaryValueCallBacks);
814 }
815 CFDictionaryAddValue(builtinMapping, sourceInterface, targetInterface);
816 CFArrayRemoveValueAtIndex(targetBuiltinInterfaces, idx2);
817 matched = TRUE;
818 break;
819 }
820 }
821 if (matched) {
822 // proceed to next source interface
823 continue;
824 }
825
826 for (CFIndex idx2 = 0; idx2 < targetBuiltinInterfaceCount; idx2++) {
827 targetInterface = CFArrayGetValueAtIndex(targetBuiltinInterfaces, idx2);
828
829 if (_SCNetworkConfigurationIsInterfaceNamerMappable(sourceInterface, targetInterface, FALSE)) {
830 if (builtinMapping == NULL) {
831 builtinMapping = CFDictionaryCreateMutable(NULL, 0,
832 &kCFTypeDictionaryKeyCallBacks,
833 &kCFTypeDictionaryValueCallBacks);
834 }
835 CFDictionaryAddValue(builtinMapping, sourceInterface, targetInterface);
836 CFArrayRemoveValueAtIndex(targetBuiltinInterfaces, idx2);
837 break;
838 }
839 }
840 }
841
842 done:
843 if (sourceBuiltinInterfaces != NULL) {
844 CFRelease(sourceBuiltinInterfaces);
845 }
846 if (targetBuiltinInterfaces != NULL) {
847 CFRelease(targetBuiltinInterfaces);
848 }
849 return builtinMapping;
850 }
851
852 static CFMutableDictionaryRef
853 _SCNetworkConfigurationCopyExternalInterfaceMapping (SCPreferencesRef sourcePref, SCPreferencesRef targetPrefs)
854 {
855 CFNumberRef cfMaxTargetUnit = NULL;
856 CFNumberRef currentInterfaceUnit = NULL;
857 CFMutableDictionaryRef externalMapping = NULL;
858 CFMutableDictionaryRef interfaceTypeToMaxUnitMapping = NULL;
859 int maxTargetUnit;
860 int newTargetUnit;
861 CFIndex sourceExternalInterfaceCount = 0;
862 CFMutableArrayRef sourceExternalInterfaces = NULL;
863 SCNetworkInterfaceRef sourceInterface = NULL;
864 CFIndex targetExternalInterfaceCount = 0;
865 CFMutableArrayRef targetExternalInterfaces = NULL;
866 SCNetworkInterfaceRef targetInterface = NULL;
867 CFNumberRef type;
868
869 sourceExternalInterfaces = _SCNetworkInterfaceCopyInterfacesFilteredByBuiltinWithPreferences(sourcePref, FALSE);
870 if (!isA_CFArray(sourceExternalInterfaces)) {
871 SC_log(LOG_INFO, "No source external interfaces");
872 goto done;
873 }
874 sourceExternalInterfaceCount = CFArrayGetCount(sourceExternalInterfaces);
875 if (sourceExternalInterfaceCount == 0) {
876 SC_log(LOG_INFO, "No source external interfaces");
877 goto done;
878 }
879
880 targetExternalInterfaces = _SCNetworkInterfaceCopyInterfacesFilteredByBuiltinWithPreferences(targetPrefs, FALSE);
881 if (!isA_CFArray(targetExternalInterfaces)) {
882 SC_log(LOG_INFO, "No target external interfaces");
883 goto done;
884 }
885
886 interfaceTypeToMaxUnitMapping = _SCNetworkInterfaceStorageCopyMaxUnitPerInterfaceType(targetPrefs);
887 externalMapping = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
888
889 // Map all external interfaces which exist in both source and target
890 for (CFIndex idx = 0; idx < sourceExternalInterfaceCount; idx++) {
891 Boolean matched = FALSE;
892
893 sourceInterface = CFArrayGetValueAtIndex(sourceExternalInterfaces, idx);
894 targetExternalInterfaceCount = CFArrayGetCount(targetExternalInterfaces);
895 currentInterfaceUnit = NULL;
896
897 for (CFIndex idx2 = 0; idx2 < targetExternalInterfaceCount; idx2++) {
898 CFDataRef sourceHardwareAddress;
899 CFDataRef targetHardwareAddress;
900
901 targetInterface = CFArrayGetValueAtIndex(targetExternalInterfaces, idx2);
902 sourceHardwareAddress = _SCNetworkInterfaceGetHardwareAddress(sourceInterface);
903 targetHardwareAddress = _SCNetworkInterfaceGetHardwareAddress(targetInterface);
904 if (_SC_CFEqual(sourceHardwareAddress, targetHardwareAddress)) {
905 CFDictionaryAddValue(externalMapping, sourceInterface, targetInterface);
906 CFArrayRemoveValueAtIndex(targetExternalInterfaces, idx2);
907 matched = TRUE;
908 break;
909 }
910 }
911 if (matched) {
912 // proceed to next source interface
913 continue;
914 }
915
916 for (CFIndex idx2 = 0; idx2 < targetExternalInterfaceCount; idx2++) {
917 targetInterface = CFArrayGetValueAtIndex(targetExternalInterfaces, idx2);
918
919 if (_SCNetworkConfigurationIsInterfaceNamerMappable(sourceInterface, targetInterface, TRUE)) {
920 CFDictionaryAddValue(externalMapping, sourceInterface, targetInterface);
921 CFArrayRemoveValueAtIndex(targetExternalInterfaces, idx2);
922 matched = TRUE;
923 break;
924 }
925 }
926 if (matched) {
927 // proceed to next source interface
928 continue;
929 }
930
931 // Create new mappings for external source interfaces which don't exist in the target
932 type = _SCNetworkInterfaceGetIOInterfaceType(sourceInterface);
933
934 cfMaxTargetUnit = CFDictionaryGetValue(interfaceTypeToMaxUnitMapping, type);
935 if (cfMaxTargetUnit != NULL) {
936 CFNumberGetValue(cfMaxTargetUnit, kCFNumberIntType, &maxTargetUnit);
937 newTargetUnit = maxTargetUnit + 1;
938 } else {
939 newTargetUnit = 0;
940 }
941
942 cfMaxTargetUnit = CFNumberCreate(NULL, kCFNumberIntType, &newTargetUnit);
943 CFDictionarySetValue(interfaceTypeToMaxUnitMapping, type, cfMaxTargetUnit);
944
945 targetInterface = (SCNetworkInterfaceRef)__SCNetworkInterfaceCreateCopy(NULL, sourceInterface, NULL, NULL);
946
947 SC_log(LOG_INFO, "sourceInterface: %p, target Interface: %p", sourceInterface, targetInterface);
948
949 currentInterfaceUnit = _SCNetworkInterfaceGetIOInterfaceUnit(targetInterface);
950 if (!isA_CFNumber(currentInterfaceUnit) ||
951 !CFEqual(currentInterfaceUnit, cfMaxTargetUnit)) {
952 // Update the interface unit
953 __SCNetworkInterfaceSetIOInterfaceUnit(targetInterface, cfMaxTargetUnit);
954 }
955
956 CFDictionaryAddValue(externalMapping, sourceInterface, targetInterface);
957
958 CFRelease(targetInterface);
959 targetInterface = NULL;
960 CFRelease(cfMaxTargetUnit);
961 cfMaxTargetUnit = NULL;
962
963 }
964 done:
965 if (sourceExternalInterfaces != NULL) {
966 CFRelease(sourceExternalInterfaces);
967 }
968 if (targetExternalInterfaces != NULL) {
969 CFRelease(targetExternalInterfaces);
970 }
971 if (interfaceTypeToMaxUnitMapping != NULL) {
972 CFRelease(interfaceTypeToMaxUnitMapping);
973 }
974 return externalMapping;
975 }
976 static Boolean
977 __SCNetworkConfigurationInterfaceNameIsEquiv(CFStringRef interfaceName1, CFStringRef interfaceName2);
978
979 static Boolean
980 _SCNetworkConfigurationIsInterfaceNamerMappable(SCNetworkInterfaceRef interface1, SCNetworkInterfaceRef interface2, Boolean bypassActive)
981 {
982 #pragma unused(bypassActive)
983 Boolean interface1IsBuiltin;
984 CFStringRef interface1Prefix;
985 CFStringRef interface1Type;
986 CFStringRef interface1UserDefinedName;
987 Boolean interface2IsBuiltin;
988 CFStringRef interface2Prefix;
989 CFStringRef interface2Type;
990 CFStringRef interface2UserDefinedName;
991
992 if (interface1 == interface2) {
993 // No work needs to be done
994 return TRUE;
995 }
996 interface1IsBuiltin = _SCNetworkInterfaceIsBuiltin(interface1);
997 interface2IsBuiltin = _SCNetworkInterfaceIsBuiltin(interface2);
998
999 interface1UserDefinedName = SCNetworkInterfaceGetLocalizedDisplayName(interface1);
1000 interface2UserDefinedName = SCNetworkInterfaceGetLocalizedDisplayName(interface2);
1001
1002 interface1Type = SCNetworkInterfaceGetInterfaceType(interface1);
1003 interface2Type = SCNetworkInterfaceGetInterfaceType(interface2);
1004
1005 interface1Prefix = _SCNetworkInterfaceGetIOInterfaceNamePrefix(interface1);
1006 interface2Prefix = _SCNetworkInterfaceGetIOInterfaceNamePrefix(interface2);
1007
1008 // Check if have same builtin values.
1009 // Check if User Defined name matches
1010 // Check if SCNetwork Interface Type matches
1011
1012 if (interface1IsBuiltin != interface2IsBuiltin) {
1013 return FALSE;
1014 }
1015
1016 if (!_SC_CFEqual(interface1Type, interface2Type)) {
1017 return FALSE;
1018 }
1019
1020 if (!_SC_CFEqual(interface1Prefix, interface2Prefix)) {
1021 return FALSE;
1022 }
1023
1024 if (!_SC_CFEqual(interface1UserDefinedName, interface2UserDefinedName)) {
1025 // Checking if we have a mismatch because of the name Ethernet and Ethernet 1
1026 // Checking if we have a mismatch because of the name Airport and WiFi
1027 if (interface1IsBuiltin &&
1028 interface2IsBuiltin &&
1029 __SCNetworkConfigurationInterfaceNameIsEquiv(interface1UserDefinedName, interface2UserDefinedName)) {
1030 return TRUE;
1031 }
1032 return FALSE;
1033 }
1034 return TRUE;
1035 }
1036
1037 static Boolean
1038 __SCNetworkConfigurationInterfaceNameIsEquiv(CFStringRef interfaceName1, CFStringRef interfaceName2)
1039 {
1040 CFStringRef interfaceArray[] = { CFSTR("iPhone"), CFSTR("iPad"), CFSTR("iPod"), CFSTR("AppleTV") };
1041 const int interfaceCount = sizeof(interfaceArray) / sizeof(CFStringRef);
1042 CFStringRef portSuffix = CFSTR(", Port 1");
1043
1044 if ((isA_CFString(interfaceName1) != NULL) &&
1045 (isA_CFString(interfaceName2) != NULL)) {
1046 if (!CFEqual(interfaceName1, interfaceName2)) {
1047 // Check if we are looking at the WiFi interface
1048 if ((CFEqual(interfaceName1, CFSTR("AirPort")) ||
1049 (CFEqual(interfaceName1, CFSTR("Wi-Fi")))) &&
1050 (CFEqual(interfaceName2, CFSTR("AirPort")) ||
1051 (CFEqual(interfaceName2, CFSTR("Wi-Fi"))))) {
1052 return TRUE;
1053 }
1054
1055 if (((CFEqual(interfaceName1, CFSTR("Ethernet"))) ||
1056 (CFEqual(interfaceName1, CFSTR("Ethernet 1")))) &&
1057 ((CFEqual(interfaceName2, CFSTR("Ethernet"))) ||
1058 (CFEqual(interfaceName2, CFSTR("Ethernet 1"))))) {
1059 return TRUE;
1060 }
1061
1062 if ((CFStringHasSuffix(interfaceName1, portSuffix) &&
1063 (CFStringCompareWithOptions(interfaceName1, interfaceName2, CFRangeMake(0, (CFStringGetLength(interfaceName1) - CFStringGetLength(portSuffix))), 0) == kCFCompareEqualTo)) ||
1064 (CFStringHasSuffix(interfaceName2, portSuffix) &&
1065 (CFStringCompareWithOptions(interfaceName2, interfaceName1, CFRangeMake(0, (CFStringGetLength(interfaceName2) - CFStringGetLength(portSuffix))), 0) == kCFCompareEqualTo))) {
1066 return TRUE;
1067 }
1068
1069 for (CFIndex idx = 0; idx < interfaceCount; idx++) {
1070 CFStringRef tempInterfaceName = interfaceArray[idx];
1071 if ((CFEqual(interfaceName1, tempInterfaceName) ||
1072 __SCNetworkInterfaceMatchesName(interfaceName1, tempInterfaceName)) &&
1073 (CFEqual(interfaceName2, tempInterfaceName) ||
1074 __SCNetworkInterfaceMatchesName(interfaceName2, tempInterfaceName))) {
1075 return TRUE;
1076 }
1077 }
1078 } else {
1079 return TRUE;
1080 }
1081 }
1082
1083 return FALSE;
1084 }
1085
1086 typedef struct {
1087 CFDictionaryRef interfaceMapping;
1088 CFMutableArrayRef interfacesMissingServices;
1089 } SCNetworkConfigurationMissingServiceContext;
1090
1091 typedef struct {
1092 CFDictionaryRef bsdNameToBridgeServices; // Mapping of BSD Name to SCBridgeInterfaceRef
1093 CFDictionaryRef bsdNameToBondServices; // Mapping of BSD Name to SCBondInterfaceRef
1094 CFDictionaryRef bsdNameToVLANServices; // Mapping of BSD Name to SCVLANInterfaceRef
1095 CFDictionaryRef interfaceMapping;
1096 Boolean* isValid;
1097 CFMutableArrayRef interfaceToBeRemoved; // SCNetworkInterfaceRef. Services containing the interface will be removed
1098 CFMutableArrayRef interfaceToBeReplaced;// SCNetworkInterfaceRef. Services containing the interface will be replaced with default service
1099 CFMutableArrayRef interfacePreserveServiceInformation; // SCNetworkInterfaceRef. Services containing the interface will be replaced with new service which has same configuration as the current service with issue.
1100 CFMutableDictionaryRef bsdNameServiceProtocolPreserveMapping;
1101 SCPreferencesRef prefs;
1102 Boolean repair;
1103 } SCNetworkConfigurationValidityContext;
1104
1105 static void
1106 _SCNetworkConfigurationValidateInterface (const void *key, const void *value, void *context)
1107 {
1108 CFStringRef bsdName = (CFStringRef)key;
1109 SCNetworkConfigurationValidityContext *ctx = (SCNetworkConfigurationValidityContext*)context;
1110 CFDictionaryRef bsdNameToBridgeServices = ctx->bsdNameToBridgeServices;
1111 CFDictionaryRef bsdNameToBondServices = ctx->bsdNameToBondServices;
1112 CFDictionaryRef bsdNameToVLANServices = ctx->bsdNameToVLANServices;
1113 SCNetworkInterfaceRef interface = NULL;
1114 CFDictionaryRef interfaceMapping = ctx->interfaceMapping;
1115 CFStringRef interfaceUserDefinedName = NULL;
1116 Boolean repair = ctx->repair;
1117 SCNetworkInterfaceRef serviceInterface = (SCNetworkInterfaceRef)value;
1118 CFStringRef serviceInterfaceUserDefinedName = NULL;
1119 CFMutableArrayRef interfaceToBeRemoved = ctx->interfaceToBeRemoved;
1120 CFMutableArrayRef interfaceToBeReplaced = ctx->interfaceToBeReplaced;
1121 CFMutableArrayRef interfacePreserveServiceInformation = ctx->interfacePreserveServiceInformation;
1122
1123 // No work needs to be done if we have already made determination that configuration somewhere is not valid,
1124 // or we don't intend to repair invalid configuration.
1125 if ((*ctx->isValid == FALSE) && !repair) {
1126 return;
1127 }
1128
1129 // There is no interface present for the service
1130 interface = CFDictionaryGetValue(interfaceMapping, bsdName);
1131 if (interface == NULL) {
1132 if ((((bsdNameToBridgeServices != NULL) && !CFDictionaryContainsKey(bsdNameToBridgeServices, bsdName))) &&
1133 (((bsdNameToBondServices != NULL) && !CFDictionaryContainsKey(bsdNameToBondServices, bsdName))) &&
1134 (((bsdNameToVLANServices != NULL) && !CFDictionaryContainsKey(bsdNameToVLANServices, bsdName)))) {
1135 // Not a virtual interface
1136 SC_log(LOG_NOTICE,
1137 "No real interface with BSD name (%@) for service",
1138 bsdName);
1139
1140 if (repair) {
1141 CFArrayAppendValue(interfaceToBeRemoved, serviceInterface);
1142 }
1143 *ctx->isValid = FALSE;
1144 }
1145 return;
1146 }
1147
1148 // Need to compare between both SCNetworkInterfaceRefs
1149 interfaceUserDefinedName = __SCNetworkInterfaceGetUserDefinedName(interface);
1150 serviceInterfaceUserDefinedName = __SCNetworkInterfaceGetUserDefinedName(serviceInterface);
1151
1152 if (!__SCNetworkConfigurationInterfaceNameIsEquiv(interfaceUserDefinedName, serviceInterfaceUserDefinedName)) {
1153 SC_log(LOG_NOTICE,
1154 "Interface user defined name (%@) doesn't match service/interface user defined name: %@",
1155 interfaceUserDefinedName,
1156 serviceInterfaceUserDefinedName);
1157 *ctx->isValid = FALSE;
1158 // Check if the service interface name is set to localized key
1159 if (isA_CFArray(interfacePreserveServiceInformation) != NULL &&
1160 __SCNetworkInterfaceMatchesName(interfaceUserDefinedName, serviceInterfaceUserDefinedName)) {
1161 SC_log(LOG_NOTICE,
1162 "serviceInterfaceUserDefinedName: %@ is the localized key for interface name: %@",
1163 serviceInterfaceUserDefinedName,
1164 interfaceUserDefinedName);
1165 CFArrayAppendValue(interfacePreserveServiceInformation, serviceInterface);
1166 }
1167 // Add service interface to the interfaceToBeReplaced list
1168 if (isA_CFArray(interfaceToBeReplaced) != NULL) {
1169 CFArrayAppendValue(interfaceToBeReplaced, interface);
1170 }
1171 if (isA_CFArray(interfaceToBeRemoved) != NULL) {
1172 CFArrayAppendValue(interfaceToBeRemoved, serviceInterface);
1173 }
1174 return;
1175 }
1176 }
1177
1178 static void
1179 _SCNetworkConfigurationCollectMissingService(const void *key, const void *value, void *context)
1180 {
1181 CFStringRef bsdName = (CFStringRef)key;
1182 SCNetworkConfigurationMissingServiceContext *ctx = (SCNetworkConfigurationMissingServiceContext*)context;
1183 SCNetworkInterfaceRef interface = (SCNetworkInterfaceRef)value;
1184 CFMutableArrayRef interfacesMissingServices = ctx->interfacesMissingServices;
1185 CFDictionaryRef serviceInterfaceMapping = ctx->interfaceMapping;
1186
1187 if (!isA_SCNetworkInterface(interface) ||
1188 !_SCNetworkInterfaceIsBuiltin(interface)) {
1189 return;
1190 }
1191
1192 // Check if services have mapping for the BSD name of the interface
1193 if (!CFDictionaryContainsKey(serviceInterfaceMapping, bsdName)) {
1194 CFArrayAppendValue(interfacesMissingServices, interface); // Adding interface since the corresponding service seems to be missing
1195 }
1196 }
1197
1198 static Boolean
1199 _SCNetworkConfigurationCreateBuiltinInterfaceServices(SCPreferencesRef pref,
1200 SCPreferencesRef ni_pref)
1201 {
1202 SCNetworkConfigurationMissingServiceContext context;
1203 SCNetworkInterfaceRef interface = NULL;
1204 CFArrayRef interfaces = NULL;
1205 CFMutableArrayRef interfacesWithoutService = NULL;
1206 CFDictionaryRef mappingBSDNameToInterface = NULL;
1207 CFDictionaryRef mappingServiceBSDNameToInterface = NULL;
1208 CFIndex missingServiceCount = 0;
1209 Boolean success = FALSE;
1210
1211 interfaces = __SCNetworkInterfaceCopyStoredWithPreferences(ni_pref);
1212 if (interfaces == NULL) {
1213 SC_log(LOG_NOTICE, "No interfaces");
1214 goto done;
1215 }
1216
1217 mappingBSDNameToInterface = __SCNetworkInterfaceCreateMappingUsingBSDName(interfaces);
1218 CFRelease(interfaces);
1219 if (!isA_CFDictionary(mappingBSDNameToInterface)) {
1220 goto done;
1221 }
1222
1223 interfaces = __SCNetworkServiceCopyAllInterfaces(pref);
1224 if (interfaces == NULL) {
1225 SC_log(LOG_NOTICE, "No [service] interfaces");
1226 goto done;
1227 }
1228 mappingServiceBSDNameToInterface = __SCNetworkInterfaceCreateMappingUsingBSDName(interfaces);
1229 CFRelease(interfaces);
1230 if (!isA_CFDictionary(mappingServiceBSDNameToInterface)) {
1231 goto done;
1232 }
1233
1234 interfacesWithoutService = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1235
1236 context.interfaceMapping = mappingServiceBSDNameToInterface;
1237 context.interfacesMissingServices = interfacesWithoutService;
1238
1239 CFDictionaryApplyFunction(mappingBSDNameToInterface, _SCNetworkConfigurationCollectMissingService, &context);
1240 missingServiceCount = CFArrayGetCount(interfacesWithoutService);
1241
1242 success = TRUE;
1243
1244 for (CFIndex idx = 0; idx < missingServiceCount; idx++) {
1245 interface = CFArrayGetValueAtIndex(interfacesWithoutService, idx);
1246
1247 if (!__SCNetworkServiceCreate(pref, interface, NULL)) {
1248 SC_log(LOG_NOTICE, "Could not create service for interface: %@", interface);
1249 success = FALSE;
1250 }
1251 }
1252 done:
1253 if (mappingBSDNameToInterface != NULL) {
1254 CFRelease(mappingBSDNameToInterface);
1255 }
1256 if (mappingServiceBSDNameToInterface != NULL) {
1257 CFRelease(mappingServiceBSDNameToInterface);
1258 }
1259 if (interfacesWithoutService != NULL) {
1260 CFRelease(interfacesWithoutService);
1261 }
1262
1263 return success;
1264 }
1265
1266 static void
1267 add_service(const void *value, void *context)
1268 {
1269 SCNetworkConfigurationValidityContext *ctx = (SCNetworkConfigurationValidityContext *)context;
1270 SCNetworkSetRef currentSet = NULL;
1271 Boolean enabled;
1272 SCNetworkInterfaceRef interface = (SCNetworkInterfaceRef)value;
1273 CFDictionaryRef bsdNameServiceProtocolMapping = ctx->bsdNameServiceProtocolPreserveMapping;
1274 SCPreferencesRef prefs = ctx->prefs;
1275 SCNetworkServiceRef service;
1276 CFStringRef bsdName = SCNetworkInterfaceGetBSDName(interface);
1277 CFArrayRef protocolArray = NULL;
1278
1279 if (isA_CFString(bsdName)) {
1280 protocolArray = CFDictionaryGetValue(bsdNameServiceProtocolMapping, bsdName);
1281 }
1282 service = SCNetworkServiceCreate(prefs, interface);
1283 if (service == NULL) {
1284 SC_log(LOG_NOTICE, "Could not create new service");
1285 goto done;
1286 }
1287
1288 if (!SCNetworkServiceEstablishDefaultConfiguration(service)) {
1289 SC_log(LOG_NOTICE, "SCNetworkServiceEstablishDefaultConfiguration() failed");
1290 SCNetworkServiceRemove(service);
1291 goto done;
1292 }
1293
1294 if (protocolArray != NULL) {
1295 CFIndex protocolArrayCount = CFArrayGetCount(protocolArray);
1296
1297 for (CFIndex idx = 0; idx < protocolArrayCount; idx++) {
1298 CFDictionaryRef protocolInfo = CFArrayGetValueAtIndex(protocolArray, idx);
1299 CFDictionaryRef configuration = CFDictionaryGetValue(protocolInfo, kProtocolConfiguration);
1300 CFStringRef protocolType = CFDictionaryGetValue(protocolInfo, kProtocolType);
1301 CFBooleanRef cfEnabled = CFDictionaryGetValue(protocolInfo, kProtocolEnabled);
1302 if (cfEnabled) {
1303 enabled = CFBooleanGetValue(cfEnabled);
1304 } else {
1305 enabled = FALSE;
1306 }
1307 __SCNetworkServiceAddProtocolToService(service, protocolType, configuration, enabled);
1308 }
1309 }
1310
1311 // Add service to current set
1312 currentSet = SCNetworkSetCopyCurrent(prefs);
1313 if (currentSet == NULL) {
1314 SC_log(LOG_NOTICE, "Could not find current set");
1315 SCNetworkServiceRemove(service);
1316 goto done;
1317 }
1318
1319 if (!SCNetworkSetAddService(currentSet, service)) {
1320 SC_log(LOG_NOTICE, "Could not add service to current set");
1321 SCNetworkServiceRemove(service);
1322 goto done;
1323 }
1324
1325 done:
1326
1327 if (service != NULL) {
1328 CFRelease(service);
1329 }
1330 if (currentSet != NULL) {
1331 CFRelease(currentSet);
1332 }
1333 }
1334
1335 static void
1336 create_bsd_name_service_protocol_mapping(const void *value, void *context)
1337 {
1338 SCNetworkConfigurationValidityContext *ctx = (SCNetworkConfigurationValidityContext *)context;
1339 CFArrayRef interfacePreserveServiceInformation = ctx->interfacePreserveServiceInformation;
1340 CFMutableDictionaryRef bsdNameServiceProtocolMapping = ctx->bsdNameServiceProtocolPreserveMapping;
1341 SCNetworkInterfaceRef interface;
1342 SCNetworkServiceRef service = (SCNetworkServiceRef)value;
1343
1344 interface = SCNetworkServiceGetInterface(service);
1345
1346 if (CFArrayContainsValue(interfacePreserveServiceInformation, CFRangeMake(0, CFArrayGetCount(interfacePreserveServiceInformation)), interface)) {
1347 CFStringRef bsdName = SCNetworkInterfaceGetBSDName(interface);
1348 if (isA_CFString(bsdName)) {
1349
1350 CFArrayRef protocols = SCNetworkServiceCopyProtocols(service);
1351 if (protocols != NULL) {
1352 CFMutableArrayRef protocolArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1353 CFIndex protocolCount = CFArrayGetCount(protocols);
1354
1355 for (CFIndex idx = 0; idx < protocolCount; idx++) {
1356 SCNetworkProtocolRef protocol = CFArrayGetValueAtIndex(protocols, idx);
1357 CFDictionaryRef configuration = SCNetworkProtocolGetConfiguration(protocol);
1358 CFStringRef protocolType = SCNetworkProtocolGetProtocolType(protocol);
1359 Boolean enabled = SCNetworkProtocolGetEnabled(protocol);
1360
1361 if (configuration == NULL || protocolType == NULL) {
1362 continue;
1363 }
1364 CFMutableDictionaryRef protocolInfo = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
1365
1366 CFDictionaryAddValue(protocolInfo, kProtocolType, protocolType);
1367 CFDictionaryAddValue(protocolInfo, kProtocolConfiguration, configuration);
1368 CFDictionaryAddValue(protocolInfo, kProtocolEnabled, enabled ? kCFBooleanTrue : kCFBooleanFalse);
1369 CFArrayAppendValue(protocolArray, protocolInfo);
1370 CFRelease(protocolInfo);
1371 }
1372 CFDictionaryAddValue(bsdNameServiceProtocolMapping, bsdName, protocolArray);
1373 CFRelease(protocols);
1374 CFRelease(protocolArray);
1375 }
1376
1377 }
1378 }
1379 }
1380
1381 static void
1382 remove_service(const void *value, void *context)
1383 {
1384 SCNetworkConfigurationValidityContext *ctx = (SCNetworkConfigurationValidityContext *)context;
1385 SCNetworkInterfaceRef interface;
1386 SCNetworkServiceRef service = (SCNetworkServiceRef)value;
1387 CFArrayRef toBeRemoved = ctx->interfaceToBeRemoved;
1388
1389 interface = SCNetworkServiceGetInterface(service);
1390
1391 if (CFArrayContainsValue(toBeRemoved, CFRangeMake(0, CFArrayGetCount(toBeRemoved)), interface)) {
1392 SCNetworkServiceRemove(service);
1393 }
1394 }
1395
1396 static Boolean
1397 _SCNetworkConfigurationRepairUsingPreferences(SCPreferencesRef prefs,
1398 SCNetworkConfigurationValidityContext *context)
1399 {
1400 CFIndex removeCount;
1401 CFIndex replaceCount;
1402 CFArrayRef serviceList;
1403 CFArrayRef interfaceToBeRemoved = context->interfaceToBeRemoved;
1404 CFArrayRef interfaceToBeReplaced = context->interfaceToBeReplaced;
1405
1406 removeCount = CFArrayGetCount(interfaceToBeRemoved);
1407 replaceCount = CFArrayGetCount(interfaceToBeReplaced);
1408 if (removeCount == 0 &&
1409 replaceCount == 0) {
1410 // We don't have any information to repair
1411 return FALSE;
1412 }
1413 // Backup current preferences before making changes
1414 __SCNetworkConfigurationBackup(prefs, CFSTR("pre-repair"), prefs);
1415
1416 serviceList = SCNetworkServiceCopyAll(prefs);
1417 CFArrayApplyFunction(serviceList, CFRangeMake(0, CFArrayGetCount(serviceList)), create_bsd_name_service_protocol_mapping, context);
1418 CFArrayApplyFunction(serviceList, CFRangeMake(0, CFArrayGetCount(serviceList)), remove_service, (void*)context);
1419 CFArrayApplyFunction(interfaceToBeReplaced, CFRangeMake(0, replaceCount), add_service, (void*)context);
1420 CFRelease(serviceList);
1421 return TRUE;
1422 }
1423
1424 static void
1425 validate_bridge(const void *value, void *context)
1426 {
1427 SCBridgeInterfaceRef bridge = (SCBridgeInterfaceRef) value;
1428 CFArrayRef memberInterfaces = SCBridgeInterfaceGetMemberInterfaces(bridge);
1429 CFMutableArrayRef memberInterfacesMutable = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1430 SCPreferencesRef ni_prefs = (SCPreferencesRef)context;
1431
1432 for (CFIndex idx = 0; idx < CFArrayGetCount(memberInterfaces); idx++) {
1433 CFStringRef bsdName;
1434 SCNetworkInterfaceRef interface = (SCNetworkInterfaceRef)CFArrayGetValueAtIndex(memberInterfaces, idx);
1435 SCNetworkInterfaceRef memberInterface;
1436
1437 bsdName = SCNetworkInterfaceGetBSDName(interface);
1438 if (bsdName == NULL) {
1439 continue;
1440 }
1441
1442 // Check if member interface is present
1443 memberInterface = __SCNetworkInterfaceCreateWithNIPreferencesUsingBSDName(NULL, ni_prefs, bsdName);
1444 if (memberInterface != NULL) {
1445 CFArrayAppendValue(memberInterfacesMutable, memberInterface);
1446 CFRelease(memberInterface);
1447 }
1448 }
1449
1450 if (CFArrayGetCount(memberInterfacesMutable) == 0) {
1451 SC_log(LOG_NOTICE, "Removing bridge w/no member interfaces: %@", bridge);
1452 SCBridgeInterfaceRemove(bridge);
1453 } else {
1454 SCBridgeInterfaceSetMemberInterfaces(bridge, memberInterfacesMutable);
1455 }
1456 CFRelease(memberInterfacesMutable);
1457 }
1458 #if !TARGET_OS_IPHONE
1459 static void
1460 validate_bond(const void *value, void *context)
1461 {
1462 SCBondInterfaceRef bond = (SCBondInterfaceRef)value;
1463 CFArrayRef memberInterfaces = SCBondInterfaceGetMemberInterfaces(bond);
1464 CFMutableArrayRef memberInterfacesMutable = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1465 SCPreferencesRef ni_prefs = (SCPreferencesRef)context;
1466
1467 for (CFIndex idx = 0; idx < CFArrayGetCount(memberInterfaces); idx++) {
1468 CFStringRef bsdName;
1469 SCNetworkInterfaceRef interface = (SCNetworkInterfaceRef)CFArrayGetValueAtIndex(memberInterfaces, idx);
1470 SCNetworkInterfaceRef memberInterface;
1471
1472 bsdName = SCNetworkInterfaceGetBSDName(interface);
1473 if (bsdName == NULL) {
1474 continue;
1475 }
1476
1477 // Check if member interface is present
1478 memberInterface = __SCNetworkInterfaceCreateWithNIPreferencesUsingBSDName(NULL, ni_prefs, bsdName);
1479 if (memberInterface != NULL) {
1480 CFArrayAppendValue(memberInterfacesMutable, memberInterface);
1481 CFRelease(memberInterface);
1482 }
1483 }
1484
1485 if (CFArrayGetCount(memberInterfacesMutable) == 0) {
1486 SC_log(LOG_NOTICE, "Removing bond w/no member interfaces: %@", bond);
1487 SCBondInterfaceRemove(bond);
1488 } else {
1489 SCBondInterfaceSetMemberInterfaces(bond, memberInterfacesMutable);
1490 }
1491 CFRelease(memberInterfacesMutable);
1492 }
1493 #endif // !TARGET_OS_IPHONE
1494
1495 static void
1496 validate_vlan(const void *value, void *context)
1497 {
1498 CFStringRef bsdName;
1499 SCNetworkInterfaceRef interface;
1500 Boolean isValid = TRUE;
1501 SCPreferencesRef ni_prefs = (SCPreferencesRef)context;
1502 SCNetworkInterfaceRef physicalInterface;
1503 SCVLANInterfaceRef vlan = (SCVLANInterfaceRef)value;
1504
1505 physicalInterface = SCVLANInterfaceGetPhysicalInterface(vlan);
1506 bsdName = SCNetworkInterfaceGetBSDName(physicalInterface);
1507
1508 if (bsdName == NULL) {
1509 isValid = FALSE;
1510 goto done;
1511 }
1512
1513 // Check if the physical interface is present
1514 interface = __SCNetworkInterfaceCreateWithNIPreferencesUsingBSDName(NULL, ni_prefs, bsdName);
1515 if (interface == NULL) {
1516 isValid = FALSE;
1517 goto done;
1518 }
1519 CFRelease(interface);
1520
1521 done:
1522 if (!isValid) {
1523 SC_log(LOG_NOTICE, "Removing VLAN w/no physical interface: %@", vlan);
1524 SCVLANInterfaceRemove(vlan);
1525 }
1526 }
1527
1528 Boolean
1529 _SCNetworkConfigurationCheckValidityWithPreferences(SCPreferencesRef prefs,
1530 SCPreferencesRef ni_prefs,
1531 CFDictionaryRef options)
1532 {
1533 CFArrayRef allServices = NULL;
1534 CFArrayRef allSets = NULL;
1535 CFDictionaryRef bsdNameToBridgeServices = NULL;
1536 CFDictionaryRef bsdNameToBondServices = NULL;
1537 CFDictionaryRef bsdNameToVLANServices = NULL;
1538 SCNetworkConfigurationValidityContext context;
1539 CFArrayRef interfaces = NULL;
1540 CFMutableArrayRef interfaceToBeRemoved = NULL;
1541 CFMutableArrayRef interfaceToBeReplaced = NULL;
1542 CFMutableArrayRef interfacePreserveServiceInformation = NULL;
1543 CFMutableDictionaryRef bsdNameServiceProtocolPreserveMapping = NULL;
1544 Boolean isValid = TRUE;
1545 CFDictionaryRef mappingBSDNameToInterface = NULL;
1546 CFDictionaryRef mappingServiceBSDNameToInterface = NULL;
1547 CFStringRef model = NULL;
1548 CFStringRef ni_model = NULL;
1549 Boolean repairConfiguration = FALSE;
1550 Boolean revertBypassSystemInterfaces = FALSE;
1551 CFArrayRef setServiceOrder = NULL;
1552 CFArrayRef setServices = NULL;
1553
1554 if ((isA_CFDictionary(options) != NULL)) {
1555 CFBooleanRef repair = CFDictionaryGetValue(options, kSCNetworkConfigurationRepair);
1556 if (isA_CFBoolean(repair) != NULL) {
1557 repairConfiguration = CFBooleanGetValue(repair);
1558 }
1559 }
1560
1561 SC_log(LOG_INFO,
1562 "%sbypassing system interfaces for %@",
1563 _SCNetworkConfigurationBypassSystemInterfaces(prefs) ? "" : "not ",
1564 prefs);
1565
1566 if (!_SCNetworkConfigurationBypassSystemInterfaces(prefs)) {
1567 _SCNetworkConfigurationSetBypassSystemInterfaces(prefs, TRUE);
1568 revertBypassSystemInterfaces = TRUE;
1569 }
1570
1571 /*
1572 Check the validity by:
1573 - Comparing if the models are the same
1574 */
1575 model = SCPreferencesGetValue(prefs, MODEL);
1576 if (!isA_CFString(model)) {
1577 SC_log(LOG_INFO,
1578 "Configuration validity check: no \"Model\" property in preferences.plist"
1579 "\n %@",
1580 prefs);
1581 }
1582 ni_model = SCPreferencesGetValue(ni_prefs, MODEL);
1583 if (!isA_CFString(ni_model)) {
1584 SC_log(LOG_INFO,
1585 "Configuration validity check: no \"Model\" property in NetworkInterfaces.plist"
1586 "\n %@",
1587 ni_prefs);
1588 }
1589 if (isA_CFString(model) && isA_CFString(ni_model) && !CFEqual(model, ni_model)) {
1590 isValid = FALSE;
1591 SC_log(LOG_NOTICE,
1592 "Configuration validity check: model names do not match!"
1593 "\n %@"
1594 "\n %@",
1595 prefs,
1596 ni_prefs);
1597 goto done;
1598 }
1599
1600 /*
1601 - Comparing if the interfaces names mentioned in NetworkInterfaces.plist and preferences.plist match
1602 Use the functions
1603 CFDictionaryRef
1604 __SCNetworkInterfaceCreateMappingUsingBSDName(SCPreferencesRef prefs);
1605 */
1606 interfaces = __SCNetworkInterfaceCopyStoredWithPreferences(ni_prefs);
1607 if (interfaces == NULL) {
1608 SC_log(LOG_NOTICE,
1609 "Configuration validity check: no network interfaces!"
1610 "\n %@",
1611 ni_prefs);
1612 isValid = FALSE;
1613 goto done;
1614 }
1615 mappingBSDNameToInterface = __SCNetworkInterfaceCreateMappingUsingBSDName(interfaces);
1616 CFRelease(interfaces);
1617 if (!isA_CFDictionary(mappingBSDNameToInterface)) {
1618 isValid = FALSE;
1619 SC_log(LOG_NOTICE,
1620 "Configuration validity check: no BSD name to network interface mapping!"
1621 "\n %@",
1622 ni_prefs);
1623 goto done;
1624 }
1625
1626 interfaces = __SCNetworkServiceCopyAllInterfaces(prefs);
1627 if (!isA_CFArray(interfaces)) {
1628 if (interfaces != NULL) CFRelease(interfaces);
1629 isValid = FALSE;
1630 SC_log(LOG_NOTICE,
1631 "Configuration validity check: no service interfaces!"
1632 "\n %@",
1633 prefs);
1634 goto done;
1635 }
1636 mappingServiceBSDNameToInterface = __SCNetworkInterfaceCreateMappingUsingBSDName(interfaces);
1637 CFRelease(interfaces);
1638 if (!isA_CFDictionary(mappingServiceBSDNameToInterface)) {
1639 isValid = FALSE;
1640 SC_log(LOG_NOTICE,
1641 "Configuration validity check: no BSD name to service interface mapping!"
1642 "\n %@",
1643 prefs);
1644 goto done;
1645 }
1646
1647 if (repairConfiguration) {
1648 interfaceToBeRemoved = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1649 interfaceToBeReplaced = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1650 interfacePreserveServiceInformation = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1651 bsdNameServiceProtocolPreserveMapping = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
1652 #if !TARGET_OS_IPHONE
1653 bsdNameToBridgeServices = _SCNetworkMigrationCopyMappingBSDNameToBridgeServices(prefs);
1654 bsdNameToBondServices = _SCNetworkMigrationCopyMappingBSDNameToBondServices(prefs);
1655 bsdNameToVLANServices = _SCNetworkMigrationCopyMappingBSDNameToVLANServices(prefs);
1656 #endif // !TARGET_OS_IPHONE
1657 }
1658 context.interfaceMapping = mappingBSDNameToInterface;
1659 context.isValid = &isValid;
1660 context.interfaceToBeRemoved = interfaceToBeRemoved;
1661 context.interfaceToBeReplaced = interfaceToBeReplaced;
1662 context.interfacePreserveServiceInformation = interfacePreserveServiceInformation;
1663 context.bsdNameToBridgeServices = bsdNameToBridgeServices;
1664 context.bsdNameToBondServices = bsdNameToBondServices;
1665 context.bsdNameToVLANServices = bsdNameToVLANServices;
1666 context.repair = repairConfiguration;
1667 context.prefs = prefs;
1668 context.bsdNameServiceProtocolPreserveMapping = bsdNameServiceProtocolPreserveMapping;
1669
1670 CFDictionaryApplyFunction(mappingServiceBSDNameToInterface, _SCNetworkConfigurationValidateInterface, &context);
1671
1672 if (!isValid) {
1673 SC_log(LOG_NOTICE,
1674 "Configuration validity check: mismatch between interface names in NetworkInterfaces.plist and preferences.plist!"
1675 "\n %@"
1676 "\n %@",
1677 prefs,
1678 ni_prefs);
1679 if (repairConfiguration) {
1680 isValid = _SCNetworkConfigurationRepairUsingPreferences(prefs, &context);
1681 if (!isValid) {
1682 goto done;
1683 }
1684 // Save the changes if repair fixed an invalid configuration
1685 if (!SCPreferencesCommitChanges(prefs)) {
1686 SC_log(LOG_NOTICE, "SCPreferencesCommitChanges() failed");
1687 }
1688 } else {
1689 goto done;
1690 }
1691 }
1692
1693 /*
1694 - Check if all the network services mentioned in the SCNetworkSet are actually present in the SCNetworkService array
1695 */
1696 allServices = SCNetworkServiceCopyAll(prefs);
1697 if (!isA_CFArray(allServices)) {
1698 isValid = FALSE;
1699 SC_log(LOG_NOTICE,
1700 "Configuration validity check: no services!"
1701 "\n %@",
1702 prefs);
1703 goto done;
1704 }
1705
1706 allSets = SCNetworkSetCopyAll(prefs);
1707 if (!isA_CFArray(allSets)) {
1708 isValid = FALSE;
1709 SC_log(LOG_NOTICE,
1710 "Configuration validity check: no sets!"
1711 "\n %@",
1712 prefs);
1713 goto done;
1714 }
1715
1716 for (CFIndex idx = 0; ((idx < CFArrayGetCount(allSets)) && isValid); idx++) {
1717 SCNetworkSetRef set = CFArrayGetValueAtIndex(allSets, idx);
1718
1719 setServices = SCNetworkSetCopyServices(set);
1720 if (setServices == NULL) {
1721 SC_log(LOG_NOTICE,
1722 "Configuration validity check: set w/no services!"
1723 "\n %@"
1724 "\n %@",
1725 prefs,
1726 set);
1727 continue;
1728 }
1729 for (CFIndex idx2 = 0; idx2 < CFArrayGetCount(setServices); idx2++) {
1730 SCNetworkServiceRef service = CFArrayGetValueAtIndex(setServices, idx2);
1731
1732 if (!CFArrayContainsValue(allServices, CFRangeMake(0, CFArrayGetCount(allServices)), service)) {
1733 isValid = FALSE;
1734 SC_log(LOG_NOTICE,
1735 "All network services in the network set are not present in SCNetworkService array");
1736 break;
1737 }
1738 }
1739 if (!isValid) {
1740 break;
1741 }
1742
1743 /*
1744 - Check if service IDs in service order do exist in the SET
1745 */
1746 setServiceOrder = SCNetworkSetGetServiceOrder(set);
1747 if (setServiceOrder != NULL) {
1748 for (CFIndex idx2 = 0; idx2 < CFArrayGetCount(setServiceOrder); idx2++) {
1749 SCNetworkServiceRef service = CFArrayGetValueAtIndex(setServiceOrder, idx2);
1750 if (!CFArrayContainsValue(setServiceOrder, CFRangeMake(0, CFArrayGetCount(setServiceOrder)), service) &&
1751 !CFArrayContainsValue(allServices, CFRangeMake(0, CFArrayGetCount(allServices)), service)) {
1752 SC_log(LOG_NOTICE,
1753 "Service: %@ is not present in the service order for set %@",
1754 service,
1755 set);
1756 break;
1757 }
1758 }
1759 }
1760 if (setServices != NULL) {
1761 CFRelease(setServices);
1762 setServices = NULL;
1763 }
1764 }
1765
1766 /*
1767 - Check if the virtual network interfaces have valid member interfaces
1768 */
1769 CFArrayRef bridges = SCBridgeInterfaceCopyAll(prefs);
1770 if (bridges != NULL) {
1771 CFArrayApplyFunction(bridges, CFRangeMake(0, CFArrayGetCount(bridges)), validate_bridge, (void*)ni_prefs);
1772 CFRelease(bridges);
1773 }
1774 #if !TARGET_OS_IPHONE
1775 CFArrayRef bonds = SCBondInterfaceCopyAll(prefs);
1776 if (bonds != NULL) {
1777 CFArrayApplyFunction(bonds, CFRangeMake(0, CFArrayGetCount(bonds)), validate_bond, (void*)ni_prefs);
1778 CFRelease(bonds);
1779 }
1780 #endif // !TARGET_OS_IPHONE
1781 CFArrayRef vlans = SCVLANInterfaceCopyAll(prefs);
1782 if (vlans != NULL) {
1783 CFArrayApplyFunction(vlans, CFRangeMake(0, CFArrayGetCount(vlans)), validate_vlan, (void*)ni_prefs);
1784 CFRelease(vlans);
1785 }
1786
1787
1788 done:
1789 if (mappingBSDNameToInterface != NULL) {
1790 CFRelease(mappingBSDNameToInterface);
1791 }
1792 if (mappingServiceBSDNameToInterface != NULL) {
1793 CFRelease(mappingServiceBSDNameToInterface);
1794 }
1795 if (allServices != NULL) {
1796 CFRelease(allServices);
1797 }
1798 if (allSets != NULL) {
1799 CFRelease(allSets);
1800 }
1801 #if !TARGET_OS_IPHONE
1802 if (bsdNameToBridgeServices != NULL) {
1803 CFRelease(bsdNameToBridgeServices);
1804 }
1805 if (bsdNameToBondServices != NULL) {
1806 CFRelease(bsdNameToBondServices);
1807 }
1808 if (bsdNameToVLANServices != NULL) {
1809 CFRelease(bsdNameToVLANServices);
1810 }
1811 #endif // !TARGET_OS_IPHONE
1812 if (setServices != NULL) {
1813 CFRelease(setServices);
1814 }
1815 if (interfaceToBeRemoved != NULL) {
1816 CFRelease(interfaceToBeRemoved);
1817 }
1818 if (interfaceToBeReplaced != NULL) {
1819 CFRelease(interfaceToBeReplaced);
1820 }
1821 if (interfacePreserveServiceInformation != NULL) {
1822 CFRelease(interfacePreserveServiceInformation);
1823 }
1824 if (bsdNameServiceProtocolPreserveMapping != NULL) {
1825 CFRelease(bsdNameServiceProtocolPreserveMapping);
1826 }
1827 if (revertBypassSystemInterfaces) {
1828 _SCNetworkConfigurationSetBypassSystemInterfaces(prefs, FALSE);
1829 }
1830 return isValid;
1831 }
1832
1833 Boolean
1834 _SCNetworkConfigurationCheckValidity(CFURLRef configDir, CFDictionaryRef options)
1835 {
1836 CFURLRef baseURL = NULL;
1837 CFURLRef configNetworkInterfaceFile = NULL;
1838 CFStringRef configNetworkInterfaceFileString = NULL;
1839 SCPreferencesRef configNetworkInterfacePref = NULL;
1840 SCPreferencesRef configPref = NULL;
1841 CFURLRef configPreferenceFile = NULL;
1842 CFStringRef configPreferencesFileString = NULL;
1843 Boolean isValid = FALSE;
1844 char networkInterfaceStr[PATH_MAX];
1845 char prefsStr[PATH_MAX];
1846
1847 if (configDir == NULL) {
1848 SC_log(LOG_NOTICE, "Migration files not found in directory: %@",
1849 (configDir == NULL) ? CFSTR("NULL") : CFURLGetString(configDir));
1850 goto done;
1851 }
1852 baseURL = CFURLCreateWithFileSystemPathRelativeToBase(NULL,
1853 PREFS_DEFAULT_DIR_RELATIVE,
1854 kCFURLPOSIXPathStyle,
1855 TRUE,
1856 configDir);
1857
1858 configPreferenceFile = CFURLCreateFromFileSystemRepresentationRelativeToBase(NULL,
1859 (const UInt8*)PREFS_DEFAULT_CONFIG_PLIST,
1860 sizeof(PREFS_DEFAULT_CONFIG_PLIST),
1861 FALSE,
1862 baseURL);
1863 configNetworkInterfaceFile = CFURLCreateFromFileSystemRepresentationRelativeToBase(NULL,
1864 (const UInt8*)INTERFACES_DEFAULT_CONFIG_PLIST,
1865 sizeof(INTERFACES_DEFAULT_CONFIG_PLIST),
1866 FALSE,
1867 baseURL);
1868
1869 if (!CFURLGetFileSystemRepresentation(configPreferenceFile, TRUE, (UInt8*)prefsStr, sizeof(prefsStr))) {
1870 SC_log(LOG_NOTICE, "Cannot get file system representation for url: %@", configPreferenceFile);
1871 goto done;
1872 }
1873 if (!CFURLGetFileSystemRepresentation(configNetworkInterfaceFile, TRUE, (UInt8*)networkInterfaceStr, sizeof(networkInterfaceStr))) {
1874 SC_log(LOG_NOTICE, "Cannot get file system representation for url: %@", configNetworkInterfaceFile);
1875 goto done;
1876 }
1877
1878 configPreferencesFileString = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), prefsStr);
1879 configNetworkInterfaceFileString = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), networkInterfaceStr);
1880
1881 configPref = SCPreferencesCreate(NULL,
1882 PLUGIN_ID,
1883 configPreferencesFileString);
1884
1885 configNetworkInterfacePref = SCPreferencesCreate(NULL,
1886 PLUGIN_ID,
1887 configNetworkInterfaceFileString);
1888 if ((configPref == NULL) || (configNetworkInterfacePref == NULL)) {
1889 goto done;
1890 }
1891
1892 // This function compares preferences.plist and NetworkInterfaces.plist and verifies if the values are correct
1893 // Checking interface mismatch for validity
1894 isValid = _SCNetworkConfigurationCheckValidityWithPreferences(configPref, configNetworkInterfacePref, options);
1895
1896 done:
1897 if (baseURL != NULL) {
1898 CFRelease(baseURL);
1899 }
1900 if (configPreferencesFileString != NULL) {
1901 CFRelease(configPreferencesFileString);
1902 }
1903 if (configNetworkInterfaceFileString != NULL) {
1904 CFRelease(configNetworkInterfaceFileString);
1905 }
1906 if (configPref != NULL) {
1907 CFRelease(configPref);
1908 }
1909 if (configNetworkInterfacePref != NULL) {
1910 CFRelease(configNetworkInterfacePref);
1911 }
1912 if (configPreferenceFile != NULL) {
1913 CFRelease(configPreferenceFile);
1914 }
1915 if (configNetworkInterfaceFile != NULL) {
1916 CFRelease(configNetworkInterfaceFile);
1917 }
1918 return isValid;
1919 }
1920
1921
1922 typedef struct {
1923 CFMutableArrayRef externalInterfaceList;
1924 CFMutableArrayRef networkInterfaceList;
1925 Boolean foundNewInterfaces;
1926 } SCExternalMappingContext;
1927
1928 static void
1929 _SCNetworkConfigurationCollectInterfaceStorageEntity(const void *key, const void *value, void *context)
1930 {
1931 #pragma unused(key)
1932 SCExternalMappingContext* ctx = context;
1933 CFDictionaryRef interface_entity = NULL;
1934 SCNetworkInterfaceRef targetInterface = (SCNetworkInterfaceRef)value;
1935
1936 if (CFArrayContainsValue(ctx->externalInterfaceList, CFRangeMake(0, CFArrayGetCount(ctx->externalInterfaceList)), targetInterface)) {
1937 SC_log(LOG_NOTICE, "Target interface (%@) already exists, not adding to NetworkInterfaces.plist", targetInterface);
1938 return; // If the target interface already exists then do not add it to NetworkInterfaces.plist
1939 }
1940 ctx->foundNewInterfaces = TRUE;
1941 interface_entity = __SCNetworkInterfaceCopyStorageEntity(targetInterface);
1942
1943 if (interface_entity != NULL) {
1944 CFArrayAppendValue(ctx->networkInterfaceList, interface_entity);
1945 CFRelease(interface_entity);
1946 }
1947 }
1948
1949 static CFArrayRef // CFDictionaryRef
1950 _SCNetworkMigrationCreateNetworkInterfaceArray(SCPreferencesRef ni_prefs, CFDictionaryRef externalMapping, Boolean *hasNewInterface)
1951 {
1952 SCExternalMappingContext context;
1953 CFIndex count = 0;
1954 CFMutableArrayRef externalInterfaceList = NULL;
1955 CFArrayRef if_list = NULL;
1956 CFDictionaryRef interface_entity = NULL;
1957 CFMutableArrayRef networkInterfaceList = NULL;
1958
1959 if (ni_prefs == NULL) {
1960 SC_log(LOG_NOTICE, "No NetworkInterfaces.plist");
1961 return NULL;
1962 }
1963
1964 if_list = SCPreferencesGetValue(ni_prefs, INTERFACES);
1965 if (!isA_CFArray(if_list) ||
1966 ((count = CFArrayGetCount(if_list)) == 0)) {
1967 SC_log(LOG_NOTICE, "No interfaces");
1968 return NULL;
1969 }
1970
1971 networkInterfaceList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1972
1973 // Keep the same builtin and external interfaces
1974 for (CFIndex idx = 0; idx < count; idx++) {
1975 interface_entity = CFArrayGetValueAtIndex(if_list, idx);
1976 if (!isA_CFDictionary(interface_entity)) {
1977 continue;
1978 }
1979 CFArrayAppendValue(networkInterfaceList, interface_entity);
1980 }
1981
1982 if (!isA_CFDictionary(externalMapping)) {
1983 // if no external mapping
1984 goto done;
1985 }
1986
1987 // Add any new external interfaces found
1988 externalInterfaceList = _SCNetworkInterfaceCopyInterfacesFilteredByBuiltinWithPreferences(ni_prefs, FALSE);
1989 context.externalInterfaceList = externalInterfaceList;
1990 context.networkInterfaceList = networkInterfaceList;
1991 context.foundNewInterfaces = FALSE;
1992
1993 CFDictionaryApplyFunction(externalMapping, _SCNetworkConfigurationCollectInterfaceStorageEntity, &context);
1994
1995 if (hasNewInterface != NULL) {
1996 *hasNewInterface = context.foundNewInterfaces;
1997 }
1998 done:
1999 if (externalInterfaceList != NULL) {
2000 CFRelease(externalInterfaceList);
2001 }
2002 return networkInterfaceList;
2003 }
2004
2005 static void
2006 SCNetworkMigrationMapSourceToTargetName(const void *key, const void *value, void *context)
2007 {
2008 SCNetworkInterfaceRef interfaceKey = (SCNetworkInterfaceRef)key;
2009 SCNetworkInterfaceRef interfaceValue = (SCNetworkInterfaceRef)value;
2010 CFMutableDictionaryRef mapping = (CFMutableDictionaryRef)context;
2011 CFStringRef sourceBSDName = NULL;
2012 CFStringRef targetBSDName = NULL;
2013
2014 sourceBSDName = SCNetworkInterfaceGetBSDName(interfaceKey);
2015 if (!isA_CFString(sourceBSDName)) {
2016 return;
2017 }
2018
2019 targetBSDName = SCNetworkInterfaceGetBSDName(interfaceValue);
2020 if (!isA_CFString(targetBSDName)) {
2021 return;
2022 }
2023
2024 if (!CFDictionaryContainsKey(mapping, sourceBSDName)) {
2025 CFDictionaryAddValue(mapping, sourceBSDName, targetBSDName);
2026 }
2027 return;
2028 }
2029
2030 static CFDictionaryRef
2031 _SCNetworkMigrationCreateBSDNameMapping(CFDictionaryRef internalMapping, CFDictionaryRef externalMapping)
2032 {
2033 CFMutableDictionaryRef bsdNameMapping = CFDictionaryCreateMutable(NULL, 0,
2034 &kCFTypeDictionaryKeyCallBacks,
2035 &kCFTypeDictionaryValueCallBacks);
2036
2037 if ((internalMapping == NULL) && (externalMapping == NULL)) {
2038 goto done;
2039 }
2040
2041 if (internalMapping != NULL) {
2042 CFDictionaryApplyFunction(internalMapping, SCNetworkMigrationMapSourceToTargetName, bsdNameMapping);
2043 }
2044
2045 if (externalMapping != NULL) {
2046 CFDictionaryApplyFunction(externalMapping, SCNetworkMigrationMapSourceToTargetName, bsdNameMapping);
2047 }
2048
2049 done:
2050 return bsdNameMapping;
2051 }
2052
2053 typedef struct {
2054 CFMutableArrayRef mutableServiceArray;
2055 SCPreferencesRef prefs;
2056 } SCNetworkServiceArrayCopyContext;
2057
2058 static CFDictionaryRef
2059 _SCNetworkMigrationCreateServiceSetMapping(SCPreferencesRef prefs)
2060 {
2061 CFMutableDictionaryRef serviceSetMapping = CFDictionaryCreateMutable(NULL, 0,
2062 &kCFTypeDictionaryKeyCallBacks,
2063 &kCFTypeDictionaryValueCallBacks);
2064 SCNetworkServiceRef service = NULL;
2065 CFArrayRef services = NULL;
2066 CFMutableArrayRef setList = NULL;
2067 CFArrayRef sets = NULL;
2068
2069 services = SCNetworkServiceCopyAll(prefs);
2070 if (services == NULL) {
2071 goto done;
2072 }
2073 for (CFIndex idx = 0; idx < CFArrayGetCount(services); idx++) {
2074 service = CFArrayGetValueAtIndex(services, idx);
2075
2076 if (!CFDictionaryContainsKey(serviceSetMapping, service)) {
2077 setList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
2078 CFDictionaryAddValue(serviceSetMapping, service, setList);
2079 CFRelease(setList);
2080 }
2081 }
2082 CFRelease(services);
2083
2084 sets = SCNetworkSetCopyAll(prefs);
2085 if (sets == NULL) {
2086 goto done;
2087 }
2088
2089 for (CFIndex idx = 0; idx < CFArrayGetCount(sets); idx++) {
2090 SCNetworkSetRef set = CFArrayGetValueAtIndex(sets, idx);
2091 services = SCNetworkSetCopyServices(set);
2092
2093 for (CFIndex idx2 = 0; idx2 < CFArrayGetCount(services); idx2++) {
2094 service = CFArrayGetValueAtIndex(services, idx2);
2095 setList = (CFMutableArrayRef)CFDictionaryGetValue(serviceSetMapping, service);
2096 if (setList != NULL) {
2097 CFArrayAppendValue(setList, set);
2098 }
2099 }
2100 CFRelease(services);
2101 }
2102
2103 done:
2104 if (sets != NULL) {
2105 CFRelease(sets);
2106 }
2107 return serviceSetMapping;
2108 }
2109
2110 static CFDictionaryRef
2111 _SCNetworkMigrationCreateSetMapping(SCPreferencesRef sourcePrefs,
2112 SCPreferencesRef targetPrefs)
2113 {
2114 SCNetworkSetRef currentSourceSet = NULL;
2115 CFMutableDictionaryRef setMapping = NULL;
2116 CFStringRef setName;
2117 CFArrayRef sourceSets = NULL;
2118 CFIndex targetCount;
2119 SCNetworkSetRef targetSet;
2120 CFArrayRef targetSets = NULL;
2121 CFMutableArrayRef targetSetsMutable = NULL;
2122
2123 sourceSets = SCNetworkSetCopyAll(sourcePrefs);
2124 targetSets = SCNetworkSetCopyAll(targetPrefs);
2125
2126 if (sourceSets == NULL ||
2127 targetSets == NULL) {
2128 goto done;
2129 }
2130 targetSetsMutable = CFArrayCreateMutableCopy(NULL, 0, targetSets);
2131 targetCount = CFArrayGetCount(targetSetsMutable);
2132
2133 setMapping = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
2134
2135 currentSourceSet = SCNetworkSetCopyCurrent(sourcePrefs);
2136
2137 // Mapping the current source set to the first target set, and setting it as current set
2138 if (currentSourceSet != NULL) {
2139 if (targetCount > 0) {
2140 targetSet = CFArrayGetValueAtIndex(targetSetsMutable, 0);
2141 CFRetain(targetSet);
2142 CFArrayRemoveValueAtIndex(targetSetsMutable, 0);
2143
2144 setName = SCNetworkSetGetName(currentSourceSet);
2145 SCNetworkSetSetName(targetSet, setName);
2146 CFDictionaryAddValue(setMapping, currentSourceSet, targetSet);
2147 SCNetworkSetSetCurrent(targetSet);
2148 CFRelease(targetSet);
2149 }
2150 else {
2151 SC_log(LOG_NOTICE, "Number of sets in the target should be at least 1, but is found to be %ld", targetCount);
2152 goto done;
2153 }
2154 }
2155
2156 for (CFIndex idx = 0; idx < CFArrayGetCount(sourceSets); idx++) {
2157 SCNetworkSetRef sourceSet = CFArrayGetValueAtIndex(sourceSets, idx);
2158
2159 if ((currentSourceSet != NULL) && CFEqual(sourceSet, currentSourceSet)) {
2160 continue;
2161 }
2162
2163 targetCount = CFArrayGetCount(targetSetsMutable);
2164 setName = SCNetworkSetGetName(sourceSet);
2165
2166 if (targetCount > 0) {
2167 targetSet = CFArrayGetValueAtIndex(targetSetsMutable, 0);
2168 CFRetain(targetSet);
2169 CFArrayRemoveValueAtIndex(targetSetsMutable, 0);
2170 } else {
2171 targetSet = SCNetworkSetCreate(targetPrefs);
2172 }
2173 SCNetworkSetSetName(targetSet, setName);
2174 CFDictionaryAddValue(setMapping, sourceSet, targetSet);
2175
2176 CFRelease(targetSet);
2177 }
2178
2179 done:
2180
2181 if (sourceSets != NULL) {
2182 CFRelease(sourceSets);
2183 }
2184 if (targetSets != NULL) {
2185 CFRelease(targetSets);
2186 }
2187 if (targetSetsMutable != NULL) {
2188 CFRelease(targetSetsMutable);
2189 }
2190 if (currentSourceSet != NULL) {
2191 CFRelease(currentSourceSet);
2192 }
2193
2194 return setMapping;
2195 }
2196
2197 // This function finds the mapping between source and target preferences (SCNetworkServicesRef -> SCNetworkServicesRef)
2198 // If there is no mapping found between source and target preferences, then the CFBooleanRef value indicating no value is found is stored (SCNetworkServicesRef -> kCFBooleanFalse)
2199 static CFDictionaryRef
2200 _SCNetworkMigrationCreateServiceMappingUsingBSDMapping(SCPreferencesRef sourcePrefs,
2201 SCPreferencesRef targetPrefs,
2202 CFDictionaryRef bsdNameMapping)
2203 {
2204 CFStringRef bsdNameMapTarget = NULL;
2205 CFMutableDictionaryRef serviceMapping = NULL; // Mapping of services between source and target configurations
2206 CFStringRef sourceBSDName = NULL;
2207 CFIndex sourceCount = 0;
2208 SCNetworkInterfaceRef sourceInterface = NULL;
2209 CFStringRef sourceInterfaceSubType = NULL; // Check interface type and subtype to be able to transfer VPN
2210 CFStringRef sourceInterfaceType = NULL;
2211 CFArrayRef sourceSCNetworkServices = NULL;
2212 CFMutableArrayRef sourceSCNetworkServicesMutable = NULL; // Source SCNetworkServiceRef mutable array
2213 SCNetworkServiceRef sourceService = NULL;
2214 CFStringRef targetBSDName = NULL;
2215 CFIndex targetCount = 0; // Count of Source and Target Services
2216 SCNetworkInterfaceRef targetInterface = NULL;
2217 CFStringRef targetInterfaceSubType = NULL; // services during migration
2218 CFStringRef targetInterfaceType = NULL;
2219 CFArrayRef targetSCNetworkServices = NULL;
2220 CFMutableArrayRef targetSCNetworkServicesMutable = NULL; // Target SCNetworkServiceRef mutable array
2221 SCNetworkServiceRef targetService = NULL;
2222
2223 // We need BSD Mapping to successfully create service mapping
2224 if (bsdNameMapping == NULL) {
2225 SC_log(LOG_NOTICE, "No BSD name mapping");
2226 goto done;
2227 }
2228 sourceSCNetworkServices = SCNetworkServiceCopyAll(sourcePrefs);
2229 if (!isA_CFArray(sourceSCNetworkServices)) {
2230 SC_log(LOG_NOTICE, "No source network services");
2231 goto done;
2232 }
2233 targetSCNetworkServices = SCNetworkServiceCopyAll(targetPrefs);
2234 if (!isA_CFArray(targetSCNetworkServices)) {
2235 SC_log(LOG_NOTICE, "No target network services");
2236 goto done;
2237 }
2238
2239 sourceCount = CFArrayGetCount(sourceSCNetworkServices);
2240
2241 sourceSCNetworkServicesMutable = CFArrayCreateMutableCopy(NULL, 0, sourceSCNetworkServices);
2242 targetSCNetworkServicesMutable = CFArrayCreateMutableCopy(NULL, 0, targetSCNetworkServices);
2243
2244 serviceMapping = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
2245
2246 for (CFIndex idx = 0; idx < sourceCount; idx++) {
2247 sourceBSDName = NULL;
2248 sourceService = NULL;
2249 sourceInterface = NULL;
2250 sourceInterfaceType = NULL;
2251 sourceInterfaceSubType = NULL;
2252 bsdNameMapTarget = NULL;
2253
2254 targetCount = CFArrayGetCount(targetSCNetworkServicesMutable);
2255 sourceService = (SCNetworkServiceRef) CFArrayGetValueAtIndex(sourceSCNetworkServicesMutable, idx);
2256
2257 sourceInterface = SCNetworkServiceGetInterface(sourceService);
2258 if (sourceInterface == NULL) {
2259 SC_log(LOG_NOTICE, "No source interface");
2260 continue;
2261 }
2262
2263 sourceInterfaceType = __SCNetworkInterfaceGetEntityType(sourceInterface);
2264 if ((isA_CFString(sourceInterfaceType) != NULL) &&
2265 (CFEqual(sourceInterfaceType, kSCValNetInterfaceTypeVPN) ||
2266 CFEqual(sourceInterfaceType, kSCValNetInterfaceTypePPP))) {
2267 sourceInterfaceSubType = __SCNetworkInterfaceGetEntitySubType(sourceInterface);
2268 if (!isA_CFString(sourceInterfaceSubType)) {
2269 SC_log(LOG_NOTICE, "No source interface SubType");
2270 continue;
2271 }
2272 }
2273 else if ((isA_CFString(sourceInterfaceType) &&
2274 !CFEqual(sourceInterfaceType, kSCValNetInterfaceTypeIPSec) &&
2275 !CFEqual(sourceInterfaceType, kSCValNetInterfaceType6to4) &&
2276 !CFEqual(sourceInterfaceType, kSCValNetInterfaceTypeLoopback)) ||
2277 !isA_CFString(sourceInterfaceType)) {
2278 sourceBSDName = SCNetworkInterfaceGetBSDName(sourceInterface);
2279 if (!isA_CFString(sourceBSDName) ||
2280 !CFDictionaryContainsKey(bsdNameMapping, sourceBSDName)) {
2281 SC_log(LOG_NOTICE, "No BSD name mapping for %@",
2282 (sourceBSDName == NULL) ? CFSTR("NULL") : sourceBSDName);
2283 continue;
2284 }
2285
2286 bsdNameMapTarget = CFDictionaryGetValue(bsdNameMapping, sourceBSDName);
2287 if (!isA_CFString(bsdNameMapTarget)) {
2288 SC_log(LOG_NOTICE, "No BSD name mapping target");
2289 continue;
2290 }
2291 }
2292 // Find the bsd name in target service
2293 for (CFIndex idx2 = 0; idx2 < targetCount; idx2++) {
2294 targetService = NULL;
2295 targetInterface = NULL;
2296 targetBSDName = NULL;
2297 targetInterfaceType = NULL;
2298 targetInterfaceSubType = NULL;
2299
2300 targetService = (SCNetworkServiceRef) CFArrayGetValueAtIndex(targetSCNetworkServicesMutable, idx2);
2301
2302 targetInterface = SCNetworkServiceGetInterface(targetService);
2303 if (targetInterface == NULL) {
2304 SC_log(LOG_NOTICE, "No target interface");
2305 continue;
2306 }
2307 SC_log(LOG_NOTICE, "targetInterface: %@", targetInterface);
2308 if (sourceBSDName != NULL) {
2309 targetBSDName = SCNetworkInterfaceGetBSDName(targetInterface);
2310 if (!isA_CFString(targetBSDName)) {
2311 SC_log(LOG_NOTICE, "No target BSD name");
2312 continue;
2313 }
2314
2315 if (CFEqual(targetBSDName, bsdNameMapTarget)) {
2316 SC_log(LOG_NOTICE, "Removing target BSD name: %@", targetBSDName);
2317 CFDictionaryAddValue(serviceMapping, sourceService, targetService);
2318 CFArrayRemoveValueAtIndex(targetSCNetworkServicesMutable, idx2);
2319 break;
2320 }
2321 } else {
2322 // Source Interface Type should be VPN
2323 targetInterfaceType = __SCNetworkInterfaceGetEntityType(targetInterface);
2324 if ((!isA_CFString(targetInterfaceType)) ||
2325 (!CFEqual(targetInterfaceType, kSCValNetInterfaceTypeVPN) &&
2326 !CFEqual(targetInterfaceType, kSCValNetInterfaceTypePPP))) {
2327 SC_log(LOG_NOTICE, "Unexpected target interface type: %@",
2328 (targetInterfaceType != NULL) ? targetInterfaceType : CFSTR("NULL"));
2329 continue;
2330 }
2331 targetInterfaceSubType = __SCNetworkInterfaceGetEntitySubType(targetInterface);
2332 if (!isA_CFString(targetInterfaceSubType)) {
2333 SC_log(LOG_NOTICE, "No target interface SubType");
2334 continue;
2335 }
2336
2337 // Check if the target interface type and the target interface sub type match
2338 if (CFEqual(targetInterfaceType, sourceInterfaceType) &&
2339 CFEqual(targetInterfaceSubType, sourceInterfaceSubType)) {
2340 SC_log(LOG_NOTICE, "Removing target BSD Name: %@ for VPN", targetBSDName);
2341 CFDictionaryAddValue(serviceMapping, sourceService, targetService);
2342 CFArrayRemoveValueAtIndex(targetSCNetworkServicesMutable, idx2);
2343 break;
2344 }
2345 }
2346 }
2347 // Check if sourceService has found a mapping or not, if not the create a NULL mapping to indicate
2348 // the this service needs to be added and not replaced
2349 if (!CFDictionaryContainsKey(serviceMapping, sourceService)) {
2350 SC_log(LOG_NOTICE, "Service needs to be added: %@", sourceService);
2351 CFDictionaryAddValue(serviceMapping, sourceService, kCFBooleanFalse);
2352 }
2353 }
2354
2355 done :
2356
2357 if (sourceSCNetworkServices != NULL) {
2358 CFRelease(sourceSCNetworkServices);
2359 }
2360 if (targetSCNetworkServices != NULL) {
2361 CFRelease(targetSCNetworkServices);
2362 }
2363 if (sourceSCNetworkServicesMutable != NULL) {
2364 CFRelease(sourceSCNetworkServicesMutable);
2365 }
2366 if (targetSCNetworkServicesMutable != NULL) {
2367 CFRelease(targetSCNetworkServicesMutable);
2368 }
2369
2370 return serviceMapping;
2371 }
2372
2373 typedef struct {
2374 SCPreferencesRef targetPrefs;
2375 CFDictionaryRef bsdMapping;
2376 CFDictionaryRef setMapping;
2377 CFDictionaryRef serviceSetMapping;
2378 } ServiceMigrationContext;
2379
2380 // value can be:
2381 // SCNetworkServiceRef: if target service needs replacement
2382 // CFBooleanRef: if target service is not present
2383 static void
2384 ServiceMigrationAddOrReplace(const void *key, const void *value, void *context)
2385 {
2386 CFDictionaryRef bsdMapping = NULL;
2387 ServiceMigrationContext *ctx = (ServiceMigrationContext*)context;
2388 CFDictionaryRef setMapping;
2389 CFDictionaryRef sourceServiceSetMapping;
2390 SCNetworkServiceRef sourceService = (SCNetworkServiceRef)key;
2391 SCPreferencesRef targetPrefs = NULL;
2392 SCNetworkServiceRef targetService = (SCNetworkServiceRef)value;
2393
2394 targetPrefs = ctx->targetPrefs;
2395 bsdMapping = ctx->bsdMapping;
2396 setMapping = ctx->setMapping;
2397 sourceServiceSetMapping = ctx->serviceSetMapping;
2398
2399 if ((setMapping != NULL || sourceServiceSetMapping != NULL)) {
2400 if (isA_SCNetworkService(targetService)) {
2401 SC_log(LOG_INFO, "Removing target service: %@", targetService);
2402 SCNetworkServiceRemove(targetService);
2403 }
2404 }
2405 SC_log(LOG_INFO, "Adding service: %@", sourceService);
2406 if (__SCNetworkServiceMigrateNew(targetPrefs, sourceService, bsdMapping, setMapping, sourceServiceSetMapping) == FALSE) {
2407 SC_log(LOG_INFO, "Could not add service: %@", sourceService);
2408 }
2409 }
2410
2411 static Boolean
2412 _SCNetworkMigrationDoServiceMigration(SCPreferencesRef sourcePrefs, SCPreferencesRef targetPrefs,
2413 CFDictionaryRef serviceMapping, CFDictionaryRef bsdMapping,
2414 CFDictionaryRef setMapping, CFDictionaryRef serviceSetMapping)
2415 {
2416 ServiceMigrationContext context;
2417 Boolean success = FALSE;
2418
2419 SC_log(LOG_INFO,
2420 "_SCNetworkMigrationDoServiceMigration() called"
2421 "\n sourcePrefs = %@"
2422 "\n targetPrefs = %@"
2423 "\n serviceMapping = %@"
2424 "\n bsdMapping = %@"
2425 "\n setMapping = %@"
2426 "\n serviceSetMapping = %@",
2427 sourcePrefs,
2428 targetPrefs,
2429 serviceMapping,
2430 bsdMapping,
2431 setMapping,
2432 serviceSetMapping);
2433
2434 if ((sourcePrefs == NULL) ||
2435 (targetPrefs == NULL) ||
2436 !isA_CFDictionary(serviceMapping) ||
2437 !isA_CFDictionary(bsdMapping)) {
2438 SC_log(LOG_INFO, "No sourcePrefs, targetPrefs, serviceMapping, or bsdMapping");
2439 goto done;
2440 }
2441 context.targetPrefs = targetPrefs;
2442 context.bsdMapping = bsdMapping;
2443 context.setMapping = setMapping;
2444 context.serviceSetMapping = serviceSetMapping;
2445
2446 CFDictionaryApplyFunction(serviceMapping, ServiceMigrationAddOrReplace, &context);
2447
2448 success = TRUE;
2449 done:
2450 return success;
2451 }
2452
2453 static Boolean
2454 _SCNetworkMigrationDoSystemMigration(SCPreferencesRef sourcePrefs, SCPreferencesRef targetPrefs)
2455 {
2456 CFStringEncoding nameEncoding;
2457 CFStringRef computerName;
2458 CFStringRef hostname;
2459 CFStringRef localHostname;
2460 CFDictionaryRef btmm = NULL;
2461 CFDictionaryRef btmmDSID = NULL;
2462 CFStringRef btmmDSIDPath;
2463 CFStringRef btmmPath;
2464
2465 SC_log(LOG_INFO,
2466 "_SCNetworkMigrationDoSystemMigration() called"
2467 "\n sourcePrefs = %@"
2468 "\n targetPrefs = %@",
2469 sourcePrefs,
2470 targetPrefs);
2471
2472 if ((sourcePrefs == NULL) ||
2473 (targetPrefs == NULL)) {
2474 return FALSE;
2475 }
2476
2477 hostname = SCPreferencesGetHostName(sourcePrefs);
2478 if (hostname != NULL) {
2479 SCPreferencesSetHostName(targetPrefs, hostname);
2480 SC_log(LOG_NOTICE, " copied HostName");
2481 }
2482
2483 localHostname = _SCPreferencesCopyLocalHostName(sourcePrefs);
2484 if (localHostname != NULL) {
2485 SCPreferencesSetLocalHostName(targetPrefs, localHostname);
2486 CFRelease(localHostname);
2487 SC_log(LOG_NOTICE, " copied LocalHostName");
2488 }
2489
2490 computerName = _SCPreferencesCopyComputerName(sourcePrefs, &nameEncoding);
2491 if (computerName != NULL) {
2492 SCPreferencesSetComputerName(targetPrefs, computerName, nameEncoding);
2493 CFRelease(computerName);
2494 SC_log(LOG_NOTICE, " copied ComputerName");
2495 }
2496
2497 btmmPath = CFStringCreateWithFormat(NULL, NULL,
2498 CFSTR("/%@/%@/%@"),
2499 kSCPrefSystem,
2500 kSCCompNetwork,
2501 BACK_TO_MY_MAC);
2502 btmm = SCPreferencesPathGetValue(sourcePrefs, btmmPath);
2503 if (btmm != NULL) {
2504 SCPreferencesPathSetValue(targetPrefs, btmmPath, btmm);
2505 }
2506 CFRelease(btmmPath);
2507
2508 btmmDSIDPath = CFStringCreateWithFormat(NULL, NULL,
2509 CFSTR("/%@/%@/%@"),
2510 kSCPrefSystem,
2511 kSCCompNetwork,
2512 BACK_TO_MY_MAC_DSIDS);
2513
2514 btmmDSID = SCPreferencesPathGetValue(sourcePrefs, btmmDSIDPath);
2515 if (btmmDSID != NULL) {
2516 SCPreferencesPathSetValue(targetPrefs, btmmDSIDPath, btmmDSID);
2517 }
2518 CFRelease(btmmDSIDPath);
2519
2520 return TRUE;
2521 }
2522
2523 #if !TARGET_OS_IPHONE
2524
2525 typedef struct {
2526 CFMutableArrayRef interfaceList;
2527 SCPreferencesRef ni_prefs;
2528 CFDictionaryRef bsdMapping;
2529 } SCVirtualInterfaceMemberListContext;
2530
2531 typedef struct {
2532 SCPreferencesRef prefs;
2533 SCPreferencesRef ni_prefs;
2534 CFDictionaryRef bsdMapping;
2535 CFDictionaryRef virtualBSDMapping;
2536 CFDictionaryRef mappingBSDNameToService;
2537 CFDictionaryRef setMapping;
2538 CFDictionaryRef serviceSetMapping;
2539 } SCVirtualInterfaceContext;
2540
2541 static void
2542 add_virtual_interface(const void *value, void *context)
2543 {
2544 SCVirtualInterfaceMemberListContext *ctx = (SCVirtualInterfaceMemberListContext*)context;
2545 CFMutableArrayRef interfaceList = ctx->interfaceList;
2546 CFDictionaryRef bsdMapping = ctx->bsdMapping;
2547 CFStringRef oldInterfaceBSDName = (CFStringRef)value;
2548 SCNetworkInterfaceRef newInterface;
2549 CFStringRef newInterfaceBSDName;
2550
2551 SC_log(LOG_INFO, "old BSD interface name: %@", oldInterfaceBSDName);
2552
2553 newInterfaceBSDName = CFDictionaryGetValue(bsdMapping, oldInterfaceBSDName);
2554 if (newInterfaceBSDName == NULL) {
2555 return;
2556 }
2557 SC_log(LOG_INFO, "new BSD interface name: %@", newInterfaceBSDName);
2558
2559 newInterface = __SCNetworkInterfaceCreateWithNIPreferencesUsingBSDName(NULL, ctx->ni_prefs, newInterfaceBSDName);
2560 if (newInterface != NULL) {
2561 SC_log(LOG_INFO, "adding interface to interfaceList: %@", newInterface);
2562 CFArrayAppendValue(interfaceList, newInterface);
2563 CFRelease(newInterface);
2564 }
2565 return;
2566 }
2567
2568 static void
2569 add_target_bridge(const void *key, const void *value, void *context)
2570 {
2571 CFStringRef bridgeName;
2572 CFDictionaryRef bridgeOptions;
2573 SCVirtualInterfaceContext *ctx = (SCVirtualInterfaceContext*)context;
2574 CFDictionaryRef bridgeBSDNameMapping = ctx->virtualBSDMapping;
2575 CFDictionaryRef bsdNameToServiceMapping = ctx->mappingBSDNameToService;
2576 SCVirtualInterfaceMemberListContext memberListContext;
2577 CFMutableArrayRef newInterfaceList;
2578 SCBridgeInterfaceRef newBridge;
2579 SCBridgeInterfaceRef oldBridge = (SCBridgeInterfaceRef)key;
2580 CFStringRef oldBSDName;
2581 CFArrayRef oldInterfaceList = (CFArrayRef)value;
2582 CFArrayRef oldServiceList;
2583 SCPreferencesRef prefs = ctx->prefs;
2584 CFDictionaryRef serviceSetMapping = ctx->serviceSetMapping;
2585 CFDictionaryRef setMapping = ctx->setMapping;
2586
2587 newInterfaceList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
2588
2589 memberListContext.bsdMapping = ctx->bsdMapping;
2590 memberListContext.interfaceList = newInterfaceList;
2591 memberListContext.ni_prefs = ctx->ni_prefs;
2592
2593 CFArrayApplyFunction(oldInterfaceList, CFRangeMake(0, CFArrayGetCount(oldInterfaceList)), add_virtual_interface, &memberListContext);
2594
2595 newBridge = SCBridgeInterfaceCreate(prefs);
2596
2597 if (!__SCBridgeInterfaceSetMemberInterfaces(newBridge, newInterfaceList)) {
2598 SC_log(LOG_NOTICE, "__SCBridgeInterfaceSetMemberInterfaces() failed");
2599 }
2600 CFRelease(newInterfaceList);
2601
2602 bridgeOptions = SCBridgeInterfaceGetOptions(oldBridge);
2603 if (bridgeOptions != NULL) {
2604 SCBridgeInterfaceSetOptions(newBridge, bridgeOptions);
2605 }
2606
2607 bridgeName = SCNetworkInterfaceGetLocalizedDisplayName(oldBridge);
2608
2609 if (bridgeName != NULL) {
2610 SCBridgeInterfaceSetLocalizedDisplayName(newBridge, bridgeName);
2611 }
2612
2613 oldBSDName = SCNetworkInterfaceGetBSDName(oldBridge);
2614 if (oldBSDName == NULL) {
2615 goto done;
2616 }
2617
2618 oldServiceList = CFDictionaryGetValue(bsdNameToServiceMapping, oldBSDName);
2619 if (oldServiceList == NULL) {
2620 goto done;
2621 }
2622
2623 for (CFIndex idx = 0; idx < CFArrayGetCount(oldServiceList); idx++) {
2624 SCNetworkServiceRef oldService = CFArrayGetValueAtIndex(oldServiceList, idx);
2625 if (!__SCNetworkServiceMigrateNew(prefs, oldService, bridgeBSDNameMapping, setMapping, serviceSetMapping)) {
2626 SC_log(LOG_NOTICE, "could not migrate bridge service: %@", oldService);
2627 }
2628 }
2629 done:
2630 CFRelease(newBridge);
2631 }
2632
2633 static void
2634 _SCNetworkMigrationRemoveBridgeServices(SCPreferencesRef prefs)
2635 {
2636 CFArrayRef services = SCNetworkServiceCopyAll(prefs);
2637
2638 for (CFIndex idx = 0; idx < CFArrayGetCount(services); idx++) {
2639 SCNetworkServiceRef service = CFArrayGetValueAtIndex(services, idx);
2640 SCNetworkInterfaceRef interface = SCNetworkServiceGetInterface(service);
2641 CFStringRef bsdName = SCNetworkInterfaceGetBSDName(interface);
2642
2643 if ((bsdName != NULL) &&
2644 (SCNetworkInterfaceGetInterfaceType(interface) == kSCNetworkInterfaceTypeBridge)) {
2645 SC_log(LOG_INFO, "removing service: %@", service);
2646 SCNetworkServiceRemove(service);
2647 }
2648 }
2649 CFRelease(services);
2650 }
2651
2652
2653 static CFDictionaryRef
2654 _SCNetworkMigrationCopyMappingBSDNameToBridgeServices(SCPreferencesRef prefs)
2655 {
2656 CFArrayRef services = SCNetworkServiceCopyAll(prefs);
2657 CFMutableDictionaryRef bridgeServices = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
2658
2659 for (CFIndex idx = 0; idx < CFArrayGetCount(services); idx++) {
2660 SCNetworkServiceRef service = CFArrayGetValueAtIndex(services, idx);
2661 SCNetworkInterfaceRef interface = SCNetworkServiceGetInterface(service);
2662 CFStringRef bsdName = SCNetworkInterfaceGetBSDName(interface);
2663
2664 if ((bsdName != NULL) &&
2665 SCNetworkInterfaceGetInterfaceType(interface) == kSCNetworkInterfaceTypeBridge) {
2666 CFMutableArrayRef serviceList;
2667 if (!CFDictionaryContainsKey(bridgeServices, bsdName)) {
2668 serviceList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
2669 CFDictionaryAddValue(bridgeServices, bsdName, serviceList);
2670 CFRelease(serviceList);
2671 }
2672 serviceList = (CFMutableArrayRef)CFDictionaryGetValue(bridgeServices, bsdName);
2673 CFArrayAppendValue(serviceList, service);
2674 }
2675 }
2676 CFRelease(services);
2677 return bridgeServices;
2678 }
2679
2680
2681 static Boolean
2682 _SCNetworkMigrationDoBridgeMigration (SCPreferencesRef sourcePrefs,
2683 SCPreferencesRef sourceNIPrefs,
2684 SCPreferencesRef targetPrefs,
2685 SCPreferencesRef targetNIPrefs,
2686 CFDictionaryRef bsdMapping,
2687 CFDictionaryRef setMapping,
2688 CFDictionaryRef serviceSetMapping)
2689 {
2690 #pragma unused(sourceNIPrefs)
2691 CFArrayRef allSourceBridges;
2692 CFArrayRef allTargetBridges;
2693 SCBridgeInterfaceRef bridge;
2694 CFMutableDictionaryRef bridgeInterfaceMapping = NULL;
2695 CFMutableDictionaryRef bridgeMapping;
2696 CFDictionaryRef bsdNameToBridgeServices;
2697 SCVirtualInterfaceContext context;
2698 CFIndex count = 0;
2699 Boolean success = FALSE;
2700
2701 allSourceBridges = SCBridgeInterfaceCopyAll(sourcePrefs);
2702 allTargetBridges = SCBridgeInterfaceCopyAll(targetPrefs);
2703
2704 bsdNameToBridgeServices = _SCNetworkMigrationCopyMappingBSDNameToBridgeServices(sourcePrefs);
2705
2706 bridgeInterfaceMapping = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
2707 bridgeMapping = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
2708
2709 // Create Bridge Interface Mapping
2710 for (CFIndex idx = 0; idx < CFArrayGetCount(allSourceBridges); idx++) {
2711 bridge = CFArrayGetValueAtIndex(allSourceBridges, idx);
2712 CFArrayRef bridgeMembers = SCBridgeInterfaceGetMemberInterfaces(bridge);
2713 CFMutableArrayRef interfaceList;
2714
2715 interfaceList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
2716 for (CFIndex idx2 = 0; idx2 < CFArrayGetCount(bridgeMembers); idx2++) {
2717 CFStringRef interfaceName = NULL;
2718 SCNetworkInterfaceRef interface = NULL;
2719
2720 interface = CFArrayGetValueAtIndex(bridgeMembers, idx2);
2721 interfaceName = SCNetworkInterfaceGetBSDName(interface);
2722
2723 if (CFDictionaryContainsKey(bsdMapping, interfaceName)) {
2724 CFStringRef bridgeNewName = CFStringCreateWithFormat(NULL, NULL, CFSTR("bridge%ld"), count);
2725 CFDictionaryAddValue(bridgeMapping, interfaceName, bridgeNewName);
2726 CFArrayAppendValue(interfaceList, interfaceName);
2727 CFRelease(bridgeNewName);
2728 count++;
2729 }
2730 }
2731 if (CFArrayGetCount(interfaceList) > 0) {
2732 CFDictionaryAddValue(bridgeInterfaceMapping, bridge, interfaceList);
2733 }
2734 CFRelease(interfaceList);
2735 }
2736 // Remove bridge services from target
2737 _SCNetworkMigrationRemoveBridgeServices(targetPrefs);
2738
2739 // Remove Target Bridges
2740 for (CFIndex idx = 0; idx < CFArrayGetCount(allTargetBridges); idx++) {
2741 bridge = CFArrayGetValueAtIndex(allTargetBridges, idx);
2742 if (!SCBridgeInterfaceRemove(bridge)) {
2743 SC_log(LOG_NOTICE, "SCBridgeInterfaceRemove() failed: %@", bridge);
2744 goto done;
2745 }
2746 }
2747
2748 context.prefs = targetPrefs;
2749 context.ni_prefs = targetNIPrefs;
2750 context.bsdMapping = bsdMapping;
2751 context.virtualBSDMapping = bridgeMapping;
2752 context.mappingBSDNameToService = bsdNameToBridgeServices;
2753 context.setMapping = setMapping;
2754 context.serviceSetMapping = serviceSetMapping;
2755
2756 // Add Bridge configurations at the target using mapping
2757 CFDictionaryApplyFunction(bridgeInterfaceMapping, add_target_bridge, &context);
2758
2759 success = TRUE;
2760 done:
2761 CFRelease(allSourceBridges);
2762 CFRelease(allTargetBridges);
2763 CFRelease(bridgeInterfaceMapping);
2764 CFRelease(bridgeMapping);
2765 CFRelease(bsdNameToBridgeServices);
2766 return success;
2767 }
2768
2769
2770 static void
2771 add_target_bond(const void *key, const void *value, void *context)
2772 {
2773 CFNumberRef bondMode;
2774 CFStringRef bondName;
2775 CFDictionaryRef bondOptions;
2776 SCVirtualInterfaceContext *ctx = (SCVirtualInterfaceContext*)context;
2777 CFDictionaryRef bondBSDNameMapping = ctx->virtualBSDMapping;
2778 CFDictionaryRef bsdNameToServiceMapping = ctx->mappingBSDNameToService;
2779 SCVirtualInterfaceMemberListContext memberListContext;
2780 CFMutableArrayRef newInterfaceList;
2781 SCBondInterfaceRef newBond;
2782 SCBondInterfaceRef oldBond = (SCBondInterfaceRef)key;
2783 CFStringRef oldBSDName;
2784 CFArrayRef oldInterfaceList = (CFArrayRef)value;
2785 CFArrayRef oldServiceList;
2786 SCPreferencesRef prefs = ctx->prefs;
2787 CFDictionaryRef serviceSetMapping = ctx->serviceSetMapping;
2788 CFDictionaryRef setMapping = ctx->setMapping;
2789
2790 newInterfaceList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
2791
2792 memberListContext.bsdMapping = ctx->bsdMapping;
2793 memberListContext.interfaceList = newInterfaceList;
2794 memberListContext.ni_prefs = ctx->ni_prefs;
2795
2796 CFArrayApplyFunction(oldInterfaceList, CFRangeMake(0, CFArrayGetCount(oldInterfaceList)), add_virtual_interface, &memberListContext);
2797
2798 newBond = SCBondInterfaceCreate(prefs);
2799 if (!__SCBondInterfaceSetMemberInterfaces(newBond, newInterfaceList)) {
2800 SC_log(LOG_NOTICE, "__SCBondInterfaceSetMemberInterfaces() failed");
2801 }
2802 CFRelease(newInterfaceList);
2803
2804 bondOptions = SCBondInterfaceGetOptions(oldBond);
2805 if (bondOptions != NULL) {
2806 SCBondInterfaceSetOptions(newBond, bondOptions);
2807 }
2808
2809 bondName = SCNetworkInterfaceGetLocalizedDisplayName(oldBond);
2810 if (bondName != NULL) {
2811 SCBondInterfaceSetLocalizedDisplayName(newBond, bondName);
2812 }
2813
2814 bondMode = SCBondInterfaceGetMode(oldBond);
2815 if (bondMode != NULL) {
2816 SCBondInterfaceSetMode(newBond, bondMode);
2817 }
2818 oldBSDName = SCNetworkInterfaceGetBSDName(oldBond);
2819 if (oldBSDName == NULL) {
2820 goto done;
2821 }
2822
2823 oldServiceList = CFDictionaryGetValue(bsdNameToServiceMapping, oldBSDName);
2824 if (oldServiceList == NULL) {
2825 goto done;
2826 }
2827
2828 for (CFIndex idx = 0; idx < CFArrayGetCount(oldServiceList); idx++) {
2829 SCNetworkServiceRef oldService = CFArrayGetValueAtIndex(oldServiceList, idx);
2830 if (!__SCNetworkServiceMigrateNew(prefs, oldService, bondBSDNameMapping, setMapping, serviceSetMapping)) {
2831 SC_log(LOG_NOTICE, "could not migrate bond service: %@", oldService);
2832 }
2833 }
2834 done:
2835 CFRelease(newBond);
2836 }
2837
2838 static void
2839 _SCNetworkMigrationRemoveBondServices(SCPreferencesRef prefs)
2840 {
2841 CFArrayRef services = SCNetworkServiceCopyAll(prefs);
2842
2843 for (CFIndex idx = 0; idx < CFArrayGetCount(services); idx++) {
2844 SCNetworkServiceRef service = CFArrayGetValueAtIndex(services, idx);
2845 SCNetworkInterfaceRef interface = SCNetworkServiceGetInterface(service);
2846 CFStringRef bsdName = SCNetworkInterfaceGetBSDName(interface);
2847
2848 if ((bsdName != NULL) &&
2849 SCNetworkInterfaceGetInterfaceType(interface) == kSCNetworkInterfaceTypeBond) {
2850 SCNetworkServiceRemove(service);
2851 }
2852 }
2853 CFRelease(services);
2854 }
2855
2856
2857 static CFDictionaryRef
2858 _SCNetworkMigrationCopyMappingBSDNameToBondServices(SCPreferencesRef prefs)
2859 {
2860 CFArrayRef services = SCNetworkServiceCopyAll(prefs);
2861 CFMutableDictionaryRef bondServices = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
2862
2863 for (CFIndex idx = 0; idx < CFArrayGetCount(services); idx++) {
2864 SCNetworkServiceRef service = CFArrayGetValueAtIndex(services, idx);
2865 SCNetworkInterfaceRef interface = SCNetworkServiceGetInterface(service);
2866 CFStringRef bsdName = SCNetworkInterfaceGetBSDName(interface);
2867
2868 if ((bsdName != NULL) &&
2869 SCNetworkInterfaceGetInterfaceType(interface) == kSCNetworkInterfaceTypeBond) {
2870 CFMutableArrayRef serviceList;
2871 if (!CFDictionaryContainsKey(bondServices, bsdName)) {
2872 serviceList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
2873 CFDictionaryAddValue(bondServices, bsdName, serviceList);
2874 CFRelease(serviceList);
2875 }
2876 serviceList = (CFMutableArrayRef)CFDictionaryGetValue(bondServices, bsdName);
2877 CFArrayAppendValue(serviceList, service);
2878 }
2879 }
2880 CFRelease(services);
2881 return bondServices;
2882 }
2883
2884
2885 static Boolean
2886 _SCNetworkMigrationDoBondMigration (SCPreferencesRef sourcePrefs,
2887 SCPreferencesRef sourceNIPrefs,
2888 SCPreferencesRef targetPrefs,
2889 SCPreferencesRef targetNIPrefs,
2890 CFDictionaryRef bsdMapping,
2891 CFDictionaryRef setMapping,
2892 CFDictionaryRef serviceSetMapping)
2893 {
2894 #pragma unused(sourceNIPrefs)
2895 CFArrayRef allSourceBonds;
2896 CFArrayRef allTargetBonds;
2897 SCBondInterfaceRef bond;
2898 CFMutableDictionaryRef bondInterfaceMapping = NULL;
2899 CFMutableDictionaryRef bondMapping;
2900 CFDictionaryRef bsdNameToBondServices;
2901 SCVirtualInterfaceContext context;
2902 CFIndex count = 0;
2903 Boolean success = FALSE;
2904
2905 allSourceBonds = SCBondInterfaceCopyAll(sourcePrefs);
2906 allTargetBonds = SCBondInterfaceCopyAll(targetPrefs);
2907
2908 bsdNameToBondServices = _SCNetworkMigrationCopyMappingBSDNameToBondServices(sourcePrefs);
2909
2910 bondInterfaceMapping = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
2911 bondMapping = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
2912 // Create Bond Interface mapping
2913 for (CFIndex idx = 0; idx < CFArrayGetCount(allSourceBonds); idx++) {
2914 bond = CFArrayGetValueAtIndex(allSourceBonds, idx);
2915 CFArrayRef bondMembers = SCBondInterfaceGetMemberInterfaces(bond);
2916 CFMutableArrayRef interfaceList;
2917
2918 interfaceList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
2919 for (CFIndex idx2 = 0; idx2 < CFArrayGetCount(bondMembers); idx2++) {
2920 CFStringRef interfaceName;
2921 SCNetworkInterfaceRef interface;
2922
2923 interface = CFArrayGetValueAtIndex(bondMembers, idx2);
2924 interfaceName = SCNetworkInterfaceGetBSDName(interface);
2925
2926 if (CFDictionaryContainsKey(bsdMapping, interfaceName)) {
2927 CFStringRef bondNewName = CFStringCreateWithFormat(NULL, NULL, CFSTR("bond%ld"), count);
2928 CFDictionaryAddValue(bondMapping, interfaceName, bondNewName);
2929 CFArrayAppendValue(interfaceList, interfaceName);
2930 CFRelease(bondNewName);
2931 count++;
2932 }
2933 }
2934 if (CFArrayGetCount(interfaceList) > 0) {
2935 CFDictionaryAddValue(bondInterfaceMapping, bond, interfaceList);
2936 }
2937 CFRelease(interfaceList);
2938 }
2939 // Remove bond services from target
2940 _SCNetworkMigrationRemoveBondServices(targetPrefs);
2941
2942 // Remove Target Bonds
2943 for (CFIndex idx = 0; idx < CFArrayGetCount(allTargetBonds); idx++) {
2944 bond = CFArrayGetValueAtIndex(allTargetBonds, idx);
2945 if (!SCBondInterfaceRemove(bond)) {
2946 SC_log(LOG_NOTICE, "SCBondInterfaceRemove() failed: %@", bond);
2947 goto done;
2948 }
2949 }
2950
2951 context.prefs = targetPrefs;
2952 context.ni_prefs = targetNIPrefs;
2953 context.bsdMapping = bsdMapping;
2954 context.virtualBSDMapping = bondMapping;
2955 context.mappingBSDNameToService = bsdNameToBondServices;
2956 context.setMapping = setMapping;
2957 context.serviceSetMapping = serviceSetMapping;
2958
2959 // Add Bond configurations at the target using mapping
2960 CFDictionaryApplyFunction(bondInterfaceMapping, add_target_bond, &context);
2961
2962 success = TRUE;
2963 done:
2964 CFRelease(allSourceBonds);
2965 CFRelease(allTargetBonds);
2966 CFRelease(bondInterfaceMapping);
2967 CFRelease(bondMapping);
2968 CFRelease(bsdNameToBondServices);
2969 return success;
2970 }
2971
2972 static void
2973 add_target_vlan(const void *value, void *context)
2974 {
2975 CFDictionaryRef bsdMapping;
2976 SCVirtualInterfaceContext *ctx = (SCVirtualInterfaceContext*)context;
2977 CFDictionaryRef bsdNameToServiceMapping = ctx->mappingBSDNameToService;
2978 SCPreferencesRef prefs = ctx->prefs;
2979 SCVLANInterfaceRef newVLAN = NULL;
2980 SCNetworkInterfaceRef newPhysicalInterface = NULL;
2981 CFStringRef newPhysicalInterfaceName;
2982 SCVLANInterfaceRef oldVLAN = (SCVLANInterfaceRef)value;
2983 CFStringRef oldBSDName;
2984 SCNetworkInterfaceRef oldPhysicalInterface;
2985 CFStringRef oldPhysicalInterfaceName;
2986 SCNetworkServiceRef oldService;
2987 CFArrayRef oldServiceList;
2988 CFDictionaryRef serviceSetMapping = ctx->serviceSetMapping;
2989 CFDictionaryRef setMapping = ctx->setMapping;
2990 CFDictionaryRef vlanBSDMapping = ctx->virtualBSDMapping;
2991 CFNumberRef vlanTag;
2992 CFStringRef vlanName;
2993 CFDictionaryRef vlanOptions;
2994
2995 bsdMapping = ctx->bsdMapping;
2996
2997 oldPhysicalInterface = SCVLANInterfaceGetPhysicalInterface(oldVLAN);
2998 if (oldPhysicalInterface == NULL) {
2999 SC_log(LOG_NOTICE, "No old VLAN physical interface");
3000 goto done;
3001 }
3002
3003 oldPhysicalInterfaceName = SCNetworkInterfaceGetBSDName(oldPhysicalInterface);
3004 if (oldPhysicalInterfaceName == NULL) {
3005 SC_log(LOG_NOTICE, "No old VLAN physical interface name");
3006 goto done;
3007 }
3008
3009 newPhysicalInterfaceName = CFDictionaryGetValue(bsdMapping, oldPhysicalInterfaceName);
3010 if (newPhysicalInterfaceName == NULL) {
3011 SC_log(LOG_NOTICE, "No new VLAN physical interface name");
3012 goto done;
3013 }
3014 newPhysicalInterface = __SCNetworkInterfaceCreateWithNIPreferencesUsingBSDName(NULL, ctx->ni_prefs, newPhysicalInterfaceName);
3015 if (newPhysicalInterface == NULL) {
3016 SC_log(LOG_NOTICE, "Could not create new VLAN physical interface");
3017 goto done;
3018 }
3019
3020 vlanTag = SCVLANInterfaceGetTag(oldVLAN);
3021 if (vlanTag == NULL) {
3022 SC_log(LOG_NOTICE, "No old VLAN interface tag");
3023 goto done;
3024 }
3025
3026 newVLAN = SCVLANInterfaceCreate(prefs, newPhysicalInterface, vlanTag);
3027 if (newVLAN == NULL) {
3028 SC_log(LOG_NOTICE, "Could not create new VLAN interface");
3029 goto done;
3030 }
3031
3032 vlanName = SCNetworkInterfaceGetLocalizedDisplayName(oldVLAN);
3033 if (vlanName != NULL) {
3034 SCVLANInterfaceSetLocalizedDisplayName(newVLAN, vlanName);
3035 }
3036
3037 vlanOptions = SCVLANInterfaceGetOptions(oldVLAN);
3038 if (vlanOptions != NULL) {
3039 SCVLANInterfaceSetOptions(newVLAN, vlanOptions);
3040 }
3041 oldBSDName = SCNetworkInterfaceGetBSDName(oldVLAN);
3042
3043 if (oldBSDName == NULL) {
3044 goto done;
3045 }
3046
3047 oldServiceList = CFDictionaryGetValue(bsdNameToServiceMapping, oldBSDName);
3048 if (oldServiceList == NULL) {
3049 goto done;
3050 }
3051
3052 for (CFIndex idx = 0; idx < CFArrayGetCount(oldServiceList); idx++) {
3053 oldService = CFArrayGetValueAtIndex(oldServiceList, idx);
3054 if (!__SCNetworkServiceMigrateNew(prefs, oldService, vlanBSDMapping, setMapping, serviceSetMapping)) {
3055 SC_log(LOG_NOTICE, "Could not migrate VLAN service: %@", oldService);
3056 }
3057 }
3058
3059 done:
3060 if (newPhysicalInterface != NULL) {
3061 CFRelease(newPhysicalInterface);
3062 }
3063 if (newVLAN != NULL) {
3064 CFRelease(newVLAN);
3065 }
3066 }
3067
3068 static void
3069 _SCNetworkMigrationRemoveVLANServices(SCPreferencesRef prefs)
3070 {
3071 CFArrayRef services = SCNetworkServiceCopyAll(prefs);
3072
3073 for (CFIndex idx = 0; idx < CFArrayGetCount(services); idx++) {
3074 SCNetworkServiceRef service = CFArrayGetValueAtIndex(services, idx);
3075 SCNetworkInterfaceRef interface = SCNetworkServiceGetInterface(service);
3076 CFStringRef bsdName = SCNetworkInterfaceGetBSDName(interface);
3077
3078 if ((bsdName != NULL) &&
3079 SCNetworkInterfaceGetInterfaceType(interface) == kSCNetworkInterfaceTypeVLAN) {
3080 SCNetworkServiceRemove(service);
3081 }
3082 }
3083
3084 CFRelease(services);
3085 }
3086
3087
3088 static CFDictionaryRef
3089 _SCNetworkMigrationCopyMappingBSDNameToVLANServices(SCPreferencesRef prefs)
3090 {
3091 CFArrayRef services = SCNetworkServiceCopyAll(prefs);
3092 CFMutableDictionaryRef vlanServices = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
3093
3094 for (CFIndex idx = 0; idx < CFArrayGetCount(services); idx++) {
3095 SCNetworkServiceRef service = CFArrayGetValueAtIndex(services, idx);
3096 SCNetworkInterfaceRef interface = SCNetworkServiceGetInterface(service);
3097 CFStringRef bsdName = SCNetworkInterfaceGetBSDName(interface);
3098
3099 if ((bsdName != NULL) &&
3100 SCNetworkInterfaceGetInterfaceType(interface) == kSCNetworkInterfaceTypeVLAN) {
3101 CFMutableArrayRef serviceList;
3102 if (!CFDictionaryContainsKey(vlanServices, bsdName)) {
3103 serviceList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
3104 CFDictionaryAddValue(vlanServices, bsdName, serviceList);
3105 CFRelease(serviceList);
3106 }
3107 serviceList = (CFMutableArrayRef)CFDictionaryGetValue(vlanServices, bsdName);
3108 CFArrayAppendValue(serviceList, service);
3109 }
3110 }
3111 CFRelease(services);
3112 return vlanServices;
3113 }
3114
3115 static Boolean
3116 _SCNetworkMigrationDoVLANMigration (SCPreferencesRef sourcePrefs,
3117 SCPreferencesRef sourceNIPrefs,
3118 SCPreferencesRef targetPrefs,
3119 SCPreferencesRef targetNIPrefs,
3120 CFDictionaryRef bsdMapping,
3121 CFDictionaryRef setMapping,
3122 CFDictionaryRef serviceSetMapping)
3123 {
3124 #pragma unused(sourceNIPrefs)
3125 CFArrayRef allSourceVLAN;
3126 CFArrayRef allTargetVLAN;
3127 SCVirtualInterfaceContext context;
3128 CFIndex count = 0;
3129 Boolean success = FALSE;
3130 SCVLANInterfaceRef vlan;
3131 CFMutableArrayRef vlanList;
3132 CFMutableDictionaryRef vlanMapping;
3133 CFDictionaryRef bsdNameToVLANServices;
3134
3135 allSourceVLAN = SCVLANInterfaceCopyAll(sourcePrefs);
3136 allTargetVLAN = SCVLANInterfaceCopyAll(targetPrefs);
3137
3138 bsdNameToVLANServices = _SCNetworkMigrationCopyMappingBSDNameToVLANServices(sourcePrefs);
3139
3140 vlanList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
3141 vlanMapping = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
3142
3143 for (CFIndex idx = 0; idx < CFArrayGetCount(allSourceVLAN); idx++) {
3144 vlan = CFArrayGetValueAtIndex(allSourceVLAN, idx);
3145 CFStringRef vlanBSDName = SCNetworkInterfaceGetBSDName(vlan);
3146 SCNetworkInterfaceRef physicalInterface = SCVLANInterfaceGetPhysicalInterface(vlan);
3147 CFStringRef physicalInterfaceName = SCNetworkInterfaceGetBSDName(physicalInterface);
3148
3149 // Add VLAN to be migrated if the mapping between interfaces exists
3150 if (CFDictionaryContainsKey(bsdMapping, physicalInterfaceName)) {
3151 CFStringRef vlanNewName = CFStringCreateWithFormat(NULL, NULL, CFSTR("vlan%ld"), count);
3152 CFDictionaryAddValue(vlanMapping, vlanBSDName, vlanNewName);
3153 CFArrayAppendValue(vlanList, vlan);
3154 CFRelease(vlanNewName);
3155 count++;
3156 }
3157 }
3158 // Remove vlan services from target
3159 _SCNetworkMigrationRemoveVLANServices(targetPrefs);
3160
3161 // Remove Target VLANs
3162 for (CFIndex idx = 0; idx < CFArrayGetCount(allTargetVLAN); idx++) {
3163 vlan = CFArrayGetValueAtIndex(allTargetVLAN, idx);
3164 if (!SCVLANInterfaceRemove(vlan)) {
3165 SC_log(LOG_NOTICE, "SCVLANInterfaceRemove() failed: %@", vlan);
3166 goto done;
3167 }
3168 }
3169
3170 context.prefs = targetPrefs;
3171 context.ni_prefs = targetNIPrefs;
3172 context.bsdMapping = bsdMapping;
3173 context.virtualBSDMapping = vlanMapping;
3174 context.mappingBSDNameToService = bsdNameToVLANServices;
3175 context.setMapping = setMapping;
3176 context.serviceSetMapping = serviceSetMapping;
3177
3178 // Add VLAN configurations at the target using vlanList
3179 CFArrayApplyFunction(vlanList, CFRangeMake(0, CFArrayGetCount(vlanList)), add_target_vlan, &context);
3180
3181 success = TRUE;
3182 done:
3183 CFRelease(allSourceVLAN);
3184 CFRelease(allTargetVLAN);
3185 CFRelease(vlanList);
3186 CFRelease(vlanMapping);
3187 CFRelease(bsdNameToVLANServices);
3188 return success;
3189 }
3190
3191 static Boolean
3192 _SCNetworkMigrationDoVirtualNetworkInterfaceMigration(SCPreferencesRef sourcePrefs,
3193 SCPreferencesRef sourceNIPrefs,
3194 SCPreferencesRef targetPrefs,
3195 SCPreferencesRef targetNIPrefs,
3196 CFDictionaryRef bsdMapping,
3197 CFDictionaryRef setMapping,
3198 CFDictionaryRef serviceSetMapping)
3199 {
3200 // Handle Bridges
3201 if (!_SCNetworkMigrationDoBridgeMigration(sourcePrefs, sourceNIPrefs,
3202 targetPrefs, targetNIPrefs,
3203 bsdMapping, setMapping, serviceSetMapping)) {
3204 SC_log(LOG_NOTICE, "Bridge migration failed");
3205 }
3206
3207 // Handle Bonds
3208 if (!_SCNetworkMigrationDoBondMigration(sourcePrefs, sourceNIPrefs,
3209 targetPrefs, targetNIPrefs,
3210 bsdMapping, setMapping, serviceSetMapping)) {
3211 SC_log(LOG_NOTICE, "Bond migration failed");
3212 }
3213
3214 // Handle VLANs
3215 if (!_SCNetworkMigrationDoVLANMigration(sourcePrefs, sourceNIPrefs,
3216 targetPrefs, targetNIPrefs,
3217 bsdMapping, setMapping, serviceSetMapping)) {
3218 SC_log(LOG_NOTICE, "VLAN migration failed");
3219 }
3220 return TRUE;
3221 }
3222 #endif // !TARGET_OS_IPHONE
3223
3224 typedef struct {
3225 SCPreferencesRef prefs;
3226 CFArrayRef serviceOrder;
3227 CFMutableArrayRef serviceListMutable;
3228 Boolean* success;
3229 } migrated_service_context;
3230
3231 static void
3232 create_migrated_order(const void *value, void *context)
3233 {
3234 migrated_service_context *ctx = (migrated_service_context*)context;
3235 CFMutableArrayRef migratedServiceOrder = ctx->serviceListMutable;
3236 CFArrayRef targetServiceOrder = ctx->serviceOrder;
3237 CFStringRef migratedServiceID = (CFStringRef)value;
3238 Boolean *success = ctx->success;
3239
3240 if (*success == FALSE) {
3241 return;
3242 }
3243
3244 // Preserving the service order in the source configuration for the services
3245 // which were migrated into the target configuration
3246 for (CFIndex idx = 0; idx < CFArrayGetCount(targetServiceOrder); idx++) {
3247 CFStringRef targetServiceID = CFArrayGetValueAtIndex(targetServiceOrder, idx);
3248 if (CFEqual(migratedServiceID, targetServiceID)) {
3249 CFArrayAppendValue(migratedServiceOrder, migratedServiceID);
3250 return;
3251 }
3252 }
3253 }
3254
3255 static void
3256 create_non_migrated_service_list(const void *value, void *context)
3257 {
3258 migrated_service_context *ctx = (migrated_service_context*)context;
3259 CFArrayRef migratedServiceOrder = ctx->serviceOrder;
3260 CFMutableArrayRef nonMigratedService = ctx->serviceListMutable;
3261 SCPreferencesRef prefs = ctx->prefs;
3262 SCNetworkServiceRef service;
3263 Boolean *success = ctx->success;
3264 CFStringRef targetServiceID = (CFStringRef)value;
3265
3266 if (*success == FALSE) {
3267 return;
3268 }
3269
3270 // Adding all services not present in migratedServiceOrder into nonMigrated service
3271 if (CFArrayGetFirstIndexOfValue(migratedServiceOrder,
3272 CFRangeMake(0, CFArrayGetCount(migratedServiceOrder)),
3273 targetServiceID)) {
3274 // if service already present
3275 return;
3276 }
3277
3278 service = SCNetworkServiceCopy(prefs, targetServiceID);
3279 if (service == NULL) {
3280 *success = FALSE;
3281 return;
3282 }
3283
3284 CFArrayAppendValue(nonMigratedService, service);
3285 CFRelease(service);
3286 }
3287
3288 static void
3289 preserve_service_order(const void *key, const void *value, void *context)
3290 {
3291 migrated_service_context migrated_context;
3292 CFMutableArrayRef migratedServiceOrder;
3293 migrated_service_context non_migrated_context;
3294 CFMutableArrayRef nonMigratedServices;
3295 SCNetworkSetRef sourceSet = (SCNetworkSetRef)key;
3296 CFArrayRef sourceServiceOrder = NULL;
3297 Boolean *success = (Boolean*)context;
3298 SCNetworkSetRef targetSet = (SCNetworkSetRef)value;
3299 SCNetworkSetPrivateRef targetPrivate = (SCNetworkSetPrivateRef)targetSet;
3300 CFArrayRef targetServiceOrder = NULL;
3301
3302 if (*success == FALSE) {
3303 return;
3304 }
3305
3306 migratedServiceOrder = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
3307 nonMigratedServices = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
3308
3309 sourceServiceOrder = SCNetworkSetGetServiceOrder(sourceSet);
3310 if (sourceServiceOrder == NULL) {
3311 goto done;
3312 }
3313 targetServiceOrder = SCNetworkSetGetServiceOrder(targetSet);
3314 if (targetServiceOrder == NULL) {
3315 goto done;
3316 }
3317
3318 migrated_context.prefs = NULL;
3319 migrated_context.serviceOrder = targetServiceOrder;
3320 migrated_context.serviceListMutable = migratedServiceOrder;
3321 migrated_context.success = success;
3322
3323 // Creating a list of service IDs which were migrated in the target set
3324 // while maintaining the service order of the source set
3325 CFArrayApplyFunction(sourceServiceOrder, CFRangeMake(0, CFArrayGetCount(sourceServiceOrder)), create_migrated_order, &migrated_context);
3326 if (*success == FALSE) {
3327 goto done;
3328 }
3329
3330 non_migrated_context.prefs = targetPrivate->prefs;
3331 non_migrated_context.serviceOrder = migratedServiceOrder;
3332 non_migrated_context.serviceListMutable = nonMigratedServices;
3333 non_migrated_context.success = success;
3334
3335 // Creating a list of all the services which were not migrated from the source set to the
3336 // target set
3337 CFArrayApplyFunction(targetServiceOrder, CFRangeMake(0, CFArrayGetCount(targetServiceOrder)), create_non_migrated_service_list, &non_migrated_context);
3338
3339 // Remove non migrated service
3340 for (CFIndex idx = 0; idx < CFArrayGetCount(nonMigratedServices); idx++) {
3341 SCNetworkServiceRef service = CFArrayGetValueAtIndex(nonMigratedServices, idx);
3342 SCNetworkSetRemoveService(targetSet, service);
3343 }
3344 // Set migrated service order
3345 SCNetworkSetSetServiceOrder(targetSet, migratedServiceOrder);
3346
3347 // Add non migrated services
3348 for (CFIndex idx = 0; idx < CFArrayGetCount(nonMigratedServices); idx++) {
3349 SCNetworkServiceRef service = CFArrayGetValueAtIndex(nonMigratedServices, idx);
3350 (void)SCNetworkSetAddService(targetSet, service);
3351 }
3352
3353 done:
3354 CFRelease(migratedServiceOrder);
3355 CFRelease(nonMigratedServices);
3356 return;
3357
3358 }
3359
3360 static Boolean
3361 _SCNetworkMigrationDoServiceOrderMigration(SCPreferencesRef sourcePrefs,
3362 SCPreferencesRef targetPrefs,
3363 CFDictionaryRef setMapping)
3364 {
3365 #pragma unused(sourcePrefs)
3366 #pragma unused(targetPrefs)
3367 Boolean success = TRUE;
3368
3369 if (!isA_CFDictionary(setMapping)) {
3370 success = FALSE;
3371 goto done;
3372 }
3373
3374 CFDictionaryApplyFunction(setMapping, preserve_service_order, &success);
3375 done:
3376 return success;
3377 }
3378
3379
3380 // This is a function that looks at source and target network configuration
3381 // and determines what network configurations can be transferred from source to
3382 // target
3383 static Boolean
3384 _SCNetworkConfigurationMigrateConfiguration(CFURLRef sourceDir, CFURLRef targetDir)
3385 {
3386 CFDictionaryRef bsdNameMapping = NULL; // Mapping between BSD name and SCNetworkInterfaceRef to help with mapping services
3387 CFMutableDictionaryRef builtinMapping = NULL; // Mapping between builtin interfaces between source and target configurations: (SCNetworkInterfaceRef -> SCNetworkInterfaceRef)
3388 CFMutableDictionaryRef externalMapping = NULL; // Mapping between external interfaces between source and target configurations: (SCNetworkInterfaceRef -> SCNetworkInterfaceRef)
3389 Boolean migrationSuccess = FALSE;
3390 CFArrayRef newTargetNetworkInterfaceEntity = NULL; // Array of Interface Entity which used to create new target interfaces created during migration
3391 CFDictionaryRef serviceMapping = NULL; // Mapping between services of source to target. (SCNetworkServicesRef -> SCNetworkServicesRef)
3392 CFDictionaryRef setMapping = NULL;
3393 CFDictionaryRef sourceServiceSetMapping = NULL;
3394 CFArrayRef sourceConfigurationFiles = NULL; // Path to the source configuration files which need to be migrated
3395 CFStringRef sourceModel = NULL;
3396 CFURLRef sourceNetworkInterfaceFile = NULL; // Source CFURLRef for preferences.plist and NetworkInterfaces.plist
3397 char sourceNetworkInterfaceFileStr[PATH_MAX];
3398 CFStringRef sourceNetworkInterfaceFileString = NULL; // Source CFStringRef for preferences.plist and NetworkInterfaces.plist
3399 SCPreferencesRef sourceNetworkInterfacePrefs = NULL; // Source SCPreferencesRef for preferences.plist and NetworkInterfaces.plist
3400 CFURLRef sourcePreferencesFile = NULL;
3401 char sourcePreferencesFileStr[PATH_MAX];
3402 CFStringRef sourcePreferencesFileString = NULL;
3403 SCPreferencesRef sourcePrefs = NULL;
3404 CFStringRef suffix;
3405 CFArrayRef targetConfigurationFiles = NULL; // Path to the target configuration files where migration will take place to
3406 Boolean targetConfigurationFilesPresent;
3407 CFStringRef targetModel = NULL;
3408 CFURLRef targetNetworkInterfaceFile = NULL; // Target CFURLRef for preferences.plist and NetworkInterfaces.plist
3409 char targetNetworkInterfaceFileStr[PATH_MAX];
3410 CFStringRef targetNetworkInterfaceFileString = NULL; // Target CFStringRef for preferences.plist and NetworkInterfaces.plist
3411 SCPreferencesRef targetNetworkInterfacePrefs = NULL; // Target SCPreferencesRef for preferences.plist and NetworkInterfaces.plist
3412 CFURLRef targetPreferencesFile = NULL;
3413 char targetPreferencesFileStr[PATH_MAX];
3414 CFStringRef targetPreferencesFileString = NULL;
3415 SCPreferencesRef targetPrefs = NULL;
3416 Boolean isUpgradeScenario = FALSE;
3417 CFMutableDictionaryRef validityOptions = NULL;
3418
3419 SC_log(LOG_INFO,
3420 "_SCNetworkConfigurationMigrateConfiguration() called"
3421 "\n sourceDir = %@"
3422 "\n targetDir = %@",
3423 sourceDir,
3424 targetDir);
3425
3426 // Check if configuration files exist in sourceDir
3427 if (!__SCNetworkConfigurationMigrateConfigurationFilesPresent(sourceDir, &sourceConfigurationFiles, TRUE)) {
3428 SC_log(LOG_NOTICE, "sourceDir: (%@) missing configuration files", sourceDir);
3429 goto done;
3430 }
3431
3432 sourcePreferencesFile = CFArrayGetValueAtIndex(sourceConfigurationFiles, PREFERENCES_PLIST_INDEX);
3433 if (!CFURLGetFileSystemRepresentation(sourcePreferencesFile, TRUE, (UInt8*)sourcePreferencesFileStr, sizeof(sourcePreferencesFileStr))) {
3434 SC_log(LOG_NOTICE, "Cannot get file system representation for url: %@", sourcePreferencesFile);
3435 goto done;
3436 }
3437
3438 sourceNetworkInterfaceFile = CFArrayGetValueAtIndex(sourceConfigurationFiles, NETWORK_INTERFACES_PLIST_INDEX);
3439 if (!CFURLGetFileSystemRepresentation(sourceNetworkInterfaceFile, TRUE, (UInt8*)sourceNetworkInterfaceFileStr, sizeof(sourceNetworkInterfaceFileStr))) {
3440 SC_log(LOG_NOTICE, "Cannot get file system representation for url: %@", sourceNetworkInterfaceFile);
3441 goto done;
3442 }
3443
3444 sourcePreferencesFileString = CFStringCreateWithCString(NULL, sourcePreferencesFileStr, kCFStringEncodingUTF8);
3445 sourceNetworkInterfaceFileString = CFStringCreateWithCString(NULL, sourceNetworkInterfaceFileStr, kCFStringEncodingUTF8);
3446
3447 sourcePrefs = SCPreferencesCreate(NULL, PLUGIN_ID, sourcePreferencesFileString);
3448 sourceNetworkInterfacePrefs = SCPreferencesCreate(NULL, PLUGIN_ID, sourceNetworkInterfaceFileString);
3449 if ((sourcePrefs == NULL) || (sourceNetworkInterfacePrefs == NULL)) {
3450 goto done;
3451 }
3452
3453 targetConfigurationFilesPresent = __SCNetworkConfigurationMigrateConfigurationFilesPresent(targetDir, &targetConfigurationFiles, FALSE);
3454 if (!targetConfigurationFilesPresent) {
3455 // if the expected configuration files are not present in the target directory
3456 if (targetConfigurationFiles == NULL) {
3457 // but we don't know what files are needed (no target URL)
3458 SC_log(LOG_NOTICE, "targetConfigurationFiles is NULL");
3459 goto done;
3460 }
3461 }
3462
3463 targetPreferencesFile = CFArrayGetValueAtIndex(targetConfigurationFiles, PREFERENCES_PLIST_INDEX);
3464 if (!CFURLGetFileSystemRepresentation(targetPreferencesFile, TRUE, (UInt8*)targetPreferencesFileStr, sizeof(targetPreferencesFileStr))) {
3465 SC_log(LOG_NOTICE, "Cannot get file system representation for url: %@", targetPreferencesFile);
3466 goto done;
3467 }
3468 targetNetworkInterfaceFile = CFArrayGetValueAtIndex(targetConfigurationFiles, NETWORK_INTERFACES_PLIST_INDEX);
3469 if (!CFURLGetFileSystemRepresentation(targetNetworkInterfaceFile, TRUE, (UInt8*)targetNetworkInterfaceFileStr, sizeof(targetNetworkInterfaceFileStr))) {
3470 SC_log(LOG_NOTICE, "Cannot get file system representation for url: %@", targetNetworkInterfaceFile);
3471 goto done;
3472 }
3473
3474 targetPreferencesFileString = CFStringCreateWithCString(NULL, targetPreferencesFileStr, kCFStringEncodingUTF8);
3475 targetNetworkInterfaceFileString = CFStringCreateWithCString(NULL, targetNetworkInterfaceFileStr, kCFStringEncodingUTF8);
3476
3477 SC_log(LOG_INFO,
3478 "Migrating network configuration:"
3479 "\n target configuration files %s present"
3480 "\n target preferences.plist path = %@"
3481 "\n target NetworkInterfaces.plist path = %@",
3482 targetConfigurationFilesPresent ? "are" : "are not",
3483 targetPreferencesFileString,
3484 targetNetworkInterfaceFileString);
3485
3486 if (targetConfigurationFilesPresent) {
3487 targetPrefs = SCPreferencesCreate(NULL, PLUGIN_ID, targetPreferencesFileString);
3488 targetNetworkInterfacePrefs = SCPreferencesCreate(NULL, PLUGIN_ID, targetNetworkInterfaceFileString);
3489 if ((targetPrefs == NULL) || (targetNetworkInterfacePrefs == NULL)) {
3490 SC_log(LOG_NOTICE, "Could not open target prefs/ni_prefs");
3491 goto done;
3492 }
3493 } else {
3494 // create and populate a new preferences.plist
3495 targetPrefs = SCPreferencesCreate(NULL, PLUGIN_ID, targetPreferencesFileString);
3496 __SCNetworkPopulateDefaultPrefs(targetPrefs);
3497
3498 // create and populate a new NetworkInterfaces.plist
3499 targetNetworkInterfacePrefs = SCPreferencesCreateCompanion(targetPrefs, INTERFACES_DEFAULT_CONFIG);
3500 __SCNetworkPopulateDefaultNIPrefs(targetNetworkInterfacePrefs);
3501 }
3502 validityOptions = CFDictionaryCreateMutable(NULL, 0,
3503 &kCFTypeDictionaryKeyCallBacks,
3504 &kCFTypeDictionaryValueCallBacks);
3505 CFDictionaryAddValue(validityOptions, kSCNetworkConfigurationRepair, kCFBooleanTrue);
3506
3507 SC_log(LOG_INFO,
3508 "Migrating network configuration:"
3509 "\n sourcePrefs = %@"
3510 "\n sourceNetworkInterfacePrefs = %@"
3511 "\n targetPrefs = %@"
3512 "\n targetNetworkInterfacePrefs = %@",
3513 sourcePrefs,
3514 sourceNetworkInterfacePrefs,
3515 targetPrefs,
3516 targetNetworkInterfacePrefs);
3517
3518 // Setting Bypass Interface to avoid looking at system interfaces
3519 _SCNetworkConfigurationSetBypassSystemInterfaces(sourcePrefs, TRUE);
3520 _SCNetworkConfigurationSetBypassSystemInterfaces(targetPrefs, TRUE);
3521
3522 sourceModel = SCPreferencesGetValue(sourcePrefs, MODEL);
3523 targetModel = SCPreferencesGetValue(targetPrefs, MODEL);
3524
3525 isUpgradeScenario = (isA_CFString(sourceModel) && isA_CFString(targetModel) && CFStringCompare(sourceModel, targetModel, 0) == kCFCompareEqualTo);
3526 if (isUpgradeScenario) {
3527 SC_log(LOG_NOTICE, "Migrating network configuration: performing an \"upgrade\"");
3528 } else {
3529 SC_log(LOG_NOTICE, "Migrating network configuration: performing a \"migration\"");
3530 }
3531
3532 // create backup of migration source
3533 suffix = CFStringCreateWithFormat(NULL, NULL,
3534 CFSTR("pre-%s-source"),
3535 isUpgradeScenario ? "upgrade" : "migration");
3536 __SCNetworkConfigurationBackup(sourcePrefs, suffix, targetPrefs);
3537 __SCNetworkConfigurationBackup(sourceNetworkInterfacePrefs, suffix, targetPrefs);
3538 CFRelease(suffix);
3539
3540 // create backup of migration target
3541 suffix = CFStringCreateWithFormat(NULL, NULL,
3542 CFSTR("pre-%s-%starget"),
3543 isUpgradeScenario ? "upgrade" : "migration",
3544 targetConfigurationFilesPresent ? "" : "new-");
3545 __SCNetworkConfigurationBackup(targetPrefs, suffix, targetPrefs);
3546 __SCNetworkConfigurationBackup(targetNetworkInterfacePrefs, suffix, targetPrefs);
3547 CFRelease(suffix);
3548
3549 // Create services for builtin interfaces at source if they don't exist
3550 (void)_SCNetworkConfigurationCreateBuiltinInterfaceServices(sourcePrefs, sourceNetworkInterfacePrefs);
3551 // Checking validity of the source and destination preferences before continuing
3552 if (!_SCNetworkConfigurationCheckValidityWithPreferences(sourcePrefs,
3553 sourceNetworkInterfacePrefs,
3554 validityOptions)) {
3555 SC_log(LOG_NOTICE, "Source configuration not valid");
3556 goto skipServiceMigration;
3557 }
3558 // Only call this function if configuration files were not created by default
3559 if (targetConfigurationFilesPresent) {
3560 // Create services for builtin interfaces at target if they don't exist
3561 (void)_SCNetworkConfigurationCreateBuiltinInterfaceServices(targetPrefs, targetNetworkInterfacePrefs);
3562 if (!_SCNetworkConfigurationCheckValidityWithPreferences(targetPrefs,
3563 targetNetworkInterfacePrefs,
3564 validityOptions)) {
3565 SC_log(LOG_NOTICE, "Target configuration not valid");
3566 goto skipServiceMigration;
3567 }
3568 }
3569 // Upgrade scenario, source and target models match
3570 if (isUpgradeScenario) {
3571 Boolean foundNewInterface = FALSE;
3572 // Create SCPreferences to copy the target prefs
3573 SCPreferencesRef upgradeSourcePrefs = SCPreferencesCreate(NULL, CFSTR("Upgrade Source Prefs"), NULL);
3574 SCPreferencesRef upgradeSourceNIPrefs = SCPreferencesCreate(NULL, CFSTR("Upgrade Source NI Prefs"), INTERFACES_DEFAULT_CONFIG);
3575
3576 SC_log(LOG_INFO,
3577 "Migrating network configuration:"
3578 "\n upgradeSourcePrefs [temp] = %@"
3579 "\n upgradeSourceNIPrefs [temp] = %@"
3580 "\n Copying target --> upgrade, source --> target",
3581 upgradeSourcePrefs,
3582 upgradeSourceNIPrefs);
3583
3584 // Content of target prefs
3585 CFDictionaryRef targetPrefsContent = SCPreferencesPathGetValue(targetPrefs, CFSTR("/"));
3586 CFDictionaryRef targetNIPrefsContent = SCPreferencesPathGetValue(targetNetworkInterfacePrefs, CFSTR("/"));
3587
3588 // Backing up the target prefs into source prefs
3589 SCPreferencesPathSetValue(upgradeSourcePrefs, CFSTR("/"), targetPrefsContent);
3590 SCPreferencesPathSetValue(upgradeSourceNIPrefs, CFSTR("/"), targetNIPrefsContent);
3591
3592 // Copying content from the source prefs
3593 CFDictionaryRef sourcePrefsContent = SCPreferencesPathGetValue(sourcePrefs, CFSTR("/"));
3594 CFDictionaryRef sourceNIPreferencesContent = SCPreferencesPathGetValue(sourceNetworkInterfacePrefs, CFSTR("/"));
3595
3596 // Setting the contents of the source prefs into the target prefs
3597 SCPreferencesPathSetValue(targetPrefs, CFSTR("/"), sourcePrefsContent);
3598 SCPreferencesPathSetValue(targetNetworkInterfacePrefs, CFSTR("/"), sourceNIPreferencesContent);
3599
3600 // Getting the mapping of the non builtin interfaces between source and target
3601 externalMapping = _SCNetworkConfigurationCopyExternalInterfaceMapping(upgradeSourceNIPrefs, targetNetworkInterfacePrefs);
3602 SC_log(LOG_INFO,
3603 "Upgradng, external interface mapping: %@",
3604 externalMapping);
3605
3606 newTargetNetworkInterfaceEntity = _SCNetworkMigrationCreateNetworkInterfaceArray(targetNetworkInterfacePrefs, externalMapping, &foundNewInterface);
3607
3608 SC_log(LOG_INFO,
3609 "Upgrading, %s new interfaces"
3610 "\n newTargetNetworkInterfaceEntity = %@",
3611 foundNewInterface ? "found" : "no",
3612 newTargetNetworkInterfaceEntity);
3613
3614 if (foundNewInterface) {
3615 if (newTargetNetworkInterfaceEntity == NULL) {
3616 SC_log(LOG_NOTICE, "Upgrading, failed w/no new interface list");
3617 CFRelease(upgradeSourcePrefs);
3618 CFRelease(upgradeSourceNIPrefs);
3619 goto done;
3620 }
3621
3622 // add new interface mapping to NetworkInterfaces.plist
3623 if (!__SCNetworkInterfaceSaveStoredWithPreferences(targetNetworkInterfacePrefs, newTargetNetworkInterfaceEntity)) {
3624 SC_log(LOG_NOTICE, "Upgrading, failed to update NetworkInterfaces.plist");
3625 CFRelease(upgradeSourcePrefs);
3626 CFRelease(upgradeSourceNIPrefs);
3627 goto done;
3628 }
3629
3630 // create BSD name mapping to facilitate mapping of services
3631 bsdNameMapping = _SCNetworkMigrationCreateBSDNameMapping(NULL, externalMapping);
3632
3633 serviceMapping = _SCNetworkMigrationCreateServiceMappingUsingBSDMapping(upgradeSourcePrefs, targetPrefs, bsdNameMapping);
3634
3635 _SCNetworkMigrationDoServiceMigration(upgradeSourcePrefs,
3636 targetPrefs,
3637 serviceMapping,
3638 bsdNameMapping,
3639 NULL,
3640 NULL);
3641 }
3642 CFRelease(upgradeSourcePrefs);
3643 CFRelease(upgradeSourceNIPrefs);
3644 } else {
3645 builtinMapping = _SCNetworkConfigurationCopyBuiltinMapping(sourceNetworkInterfacePrefs, targetNetworkInterfacePrefs);
3646
3647 externalMapping = _SCNetworkConfigurationCopyExternalInterfaceMapping(sourceNetworkInterfacePrefs, targetNetworkInterfacePrefs);
3648 SC_log(LOG_INFO,
3649 "Migrating, external interface mapping: %@",
3650 externalMapping);
3651
3652 newTargetNetworkInterfaceEntity = _SCNetworkMigrationCreateNetworkInterfaceArray(targetNetworkInterfacePrefs, externalMapping, NULL);
3653 if (newTargetNetworkInterfaceEntity == NULL) {
3654 SC_log(LOG_NOTICE, "Migrating, failed w/no new interface list");
3655 goto done;
3656 }
3657
3658 // Write new interface mapping to NetworkInterfaces.plist
3659 if (!__SCNetworkInterfaceSaveStoredWithPreferences(targetNetworkInterfacePrefs, newTargetNetworkInterfaceEntity)) {
3660 SC_log(LOG_NOTICE, "Migrating, failed to update NetworkInterfaces.plist");
3661 goto done;
3662 }
3663
3664 // create BSD name mapping to facilitate mapping of services
3665 bsdNameMapping = _SCNetworkMigrationCreateBSDNameMapping(builtinMapping, externalMapping);
3666
3667 serviceMapping = _SCNetworkMigrationCreateServiceMappingUsingBSDMapping(sourcePrefs, targetPrefs, bsdNameMapping);
3668 if (serviceMapping == NULL) {
3669 goto done;
3670 }
3671
3672 setMapping = _SCNetworkMigrationCreateSetMapping(sourcePrefs, targetPrefs);
3673
3674 sourceServiceSetMapping = _SCNetworkMigrationCreateServiceSetMapping(sourcePrefs);
3675
3676 // Perform the migration of services
3677 if (!_SCNetworkMigrationDoServiceMigration(sourcePrefs, targetPrefs,
3678 serviceMapping, bsdNameMapping,
3679 setMapping, sourceServiceSetMapping)) {
3680 SC_log(LOG_NOTICE, "SCNetworkMigrationDoServiceMigration(): service migration failed");
3681 goto done;
3682 }
3683
3684 #if !TARGET_OS_IPHONE
3685 // Migrating Virtual Network Interface
3686 if (!_SCNetworkMigrationDoVirtualNetworkInterfaceMigration(sourcePrefs, sourceNetworkInterfacePrefs,
3687 targetPrefs, targetNetworkInterfacePrefs,
3688 bsdNameMapping, setMapping, sourceServiceSetMapping)) {
3689 SC_log(LOG_NOTICE, "SCNetworkMigrationDoServiceMigration(): virtual interface migration failed");
3690 }
3691 #endif // !TARGET_OS_IPHONE
3692 // Migrate Service Order
3693 if (!_SCNetworkMigrationDoServiceOrderMigration(sourcePrefs, targetPrefs, setMapping)) {
3694 SC_log(LOG_NOTICE, "SCNetworkMigrationDoServiceMigration(): service order migration failed");
3695 }
3696 }
3697
3698 skipServiceMigration:
3699 // Migrating System Information
3700 if (!isUpgradeScenario) {
3701 if (!_SCNetworkMigrationDoSystemMigration(sourcePrefs, targetPrefs)) {
3702 SC_log(LOG_NOTICE, "SCNetworkMigrationDoServiceMigration(): system setting migration failed");
3703 }
3704 }
3705 if (!_SCNetworkConfigurationCheckValidityWithPreferences(targetPrefs, targetNetworkInterfacePrefs, validityOptions)) {
3706 SC_log(LOG_NOTICE, "Migrated configuration not valid");
3707 goto done;
3708 }
3709 if (!SCPreferencesCommitChanges(targetPrefs)) {
3710 SC_log(LOG_NOTICE, "SCPreferencesCommitChanges(target preferences.plist) failed: %s", SCErrorString(SCError()));
3711 goto done;
3712 }
3713
3714 if (!SCPreferencesCommitChanges(targetNetworkInterfacePrefs)) {
3715 SC_log(LOG_NOTICE, "SCPreferencesCommitChanges(target NetworkInterfaces.plist) failed: %s", SCErrorString(SCError()));
3716 goto done;
3717 }
3718 migrationSuccess = TRUE;
3719
3720 done:
3721 if (setMapping != NULL) {
3722 CFRelease(setMapping);
3723 }
3724 if (sourceServiceSetMapping != NULL) {
3725 CFRelease(sourceServiceSetMapping);
3726 }
3727 if (sourceConfigurationFiles != NULL) {
3728 CFRelease(sourceConfigurationFiles);
3729 }
3730 if (targetConfigurationFiles != NULL) {
3731 CFRelease(targetConfigurationFiles);
3732 }
3733 if (sourcePreferencesFileString != NULL) {
3734 CFRelease(sourcePreferencesFileString);
3735 }
3736 if (sourceNetworkInterfaceFileString != NULL) {
3737 CFRelease(sourceNetworkInterfaceFileString);
3738 }
3739 if (targetPreferencesFileString != NULL) {
3740 CFRelease(targetPreferencesFileString);
3741 }
3742 if (targetNetworkInterfaceFileString != NULL) {
3743 CFRelease(targetNetworkInterfaceFileString);
3744 }
3745 if (newTargetNetworkInterfaceEntity != NULL) {
3746 CFRelease(newTargetNetworkInterfaceEntity);
3747 }
3748 if (builtinMapping != NULL) {
3749 CFRelease(builtinMapping);
3750 }
3751 if (externalMapping != NULL) {
3752 CFRelease(externalMapping);
3753 }
3754 if (bsdNameMapping != NULL) {
3755 CFRelease(bsdNameMapping);
3756 }
3757 if (serviceMapping != NULL) {
3758 CFRelease(serviceMapping);
3759 }
3760 if (targetPrefs != NULL) {
3761 CFRelease(targetPrefs);
3762 }
3763 if (sourcePrefs != NULL) {
3764 CFRelease(sourcePrefs);
3765 }
3766 if (sourceNetworkInterfacePrefs != NULL) {
3767 CFRelease(sourceNetworkInterfacePrefs);
3768 }
3769 if (targetNetworkInterfacePrefs != NULL) {
3770 CFRelease(targetNetworkInterfacePrefs);
3771 }
3772 if (validityOptions != NULL) {
3773 CFRelease(validityOptions);
3774 }
3775 return migrationSuccess;
3776 }
3777
3778 #define N_QUICK 64
3779
3780 static Boolean
3781 _SCNetworkMigrationAreServicesIdentical(SCPreferencesRef configPref, SCPreferencesRef expectedConfigPref)
3782 {
3783 const void * expected_vals_q[N_QUICK];
3784 const void ** expected_vals = expected_vals_q;
3785 CFMutableArrayRef expectedServiceArray = NULL;
3786 CFIndex expectedServiceArrayCount = 0;
3787 CFDictionaryRef expectedServiceDict = NULL;
3788 size_t expectedServiceDictCount = 0;
3789 CFDictionaryRef expectedServiceEntity = 0;
3790 Boolean foundMatch = FALSE;
3791 CFMutableArrayRef serviceArray = NULL;
3792 CFIndex serviceArrayCount = 0;
3793 CFDictionaryRef serviceDict = NULL;
3794 size_t serviceDictCount = 0;
3795 CFDictionaryRef serviceEntity = NULL;
3796 Boolean success = FALSE;
3797 const void * vals_q[N_QUICK];
3798 const void ** vals = vals_q;
3799
3800 serviceDict = SCPreferencesGetValue(configPref, kSCPrefNetworkServices);
3801 if (!isA_CFDictionary(serviceDict)) {
3802 goto done;
3803 }
3804 serviceDictCount = CFDictionaryGetCount(serviceDict);
3805
3806 expectedServiceDict = SCPreferencesGetValue(expectedConfigPref, kSCPrefNetworkServices);
3807 if (!isA_CFDictionary(expectedServiceDict)) {
3808 goto done;
3809 }
3810 expectedServiceDictCount = CFDictionaryGetCount(expectedServiceDict);
3811
3812 if (serviceDictCount != expectedServiceDictCount) {
3813 goto done;
3814 }
3815
3816 if (serviceDictCount > (sizeof(vals_q) / sizeof(CFTypeRef))) {
3817 vals = CFAllocatorAllocate(NULL, serviceDictCount * sizeof(CFPropertyListRef), 0);
3818 }
3819
3820 CFDictionaryGetKeysAndValues(serviceDict, NULL, vals);
3821 serviceArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
3822
3823 for (size_t idx=0; idx < serviceDictCount; idx++) {
3824 serviceEntity = vals[idx];
3825 if (!isA_CFDictionary(serviceEntity)) {
3826 continue;
3827 }
3828 CFArrayAppendValue(serviceArray, serviceEntity);
3829 }
3830
3831 serviceArrayCount = CFArrayGetCount(serviceArray);
3832
3833 if (expectedServiceDictCount > (sizeof(expected_vals_q) / sizeof(CFTypeRef))) {
3834 expected_vals = CFAllocatorAllocate(NULL, expectedServiceDictCount, 0);
3835 }
3836
3837 CFDictionaryGetKeysAndValues(expectedServiceDict, NULL, expected_vals);
3838 expectedServiceArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
3839
3840 for (size_t idx = 0; idx < expectedServiceDictCount; idx++) {
3841 serviceEntity = expected_vals[idx];
3842 if (!isA_CFDictionary(serviceEntity)) {
3843 continue;
3844 }
3845 CFArrayAppendValue(expectedServiceArray, serviceEntity);
3846 }
3847 expectedServiceArrayCount = CFArrayGetCount(expectedServiceArray);
3848
3849 if (serviceArrayCount != expectedServiceArrayCount) {
3850 goto done;
3851 }
3852
3853 for (CFIndex idx = 0; idx < expectedServiceArrayCount; idx++) {
3854 foundMatch = FALSE;
3855 expectedServiceEntity = CFArrayGetValueAtIndex(expectedServiceArray, idx);
3856 serviceArrayCount = CFArrayGetCount(serviceArray);
3857
3858 for (CFIndex idx2 = 0; idx2 < serviceArrayCount; idx2++) {
3859 serviceEntity = CFArrayGetValueAtIndex(serviceArray, idx2);
3860
3861 if (CFEqual(expectedServiceEntity, serviceEntity)) {
3862 foundMatch = TRUE;
3863 break;
3864 }
3865 }
3866
3867 if (!foundMatch) {
3868 break;
3869 }
3870 }
3871
3872 success = foundMatch;
3873 done:
3874 if (vals != vals_q) {
3875 CFAllocatorDeallocate(NULL, vals);
3876 }
3877 if (expected_vals != expected_vals_q) {
3878 CFAllocatorDeallocate(NULL, expected_vals);
3879 }
3880 return success;
3881 }
3882
3883 static Boolean
3884 _SCNetworkMigrationAreNetworkInterfaceConfigurationsIdentical (SCPreferencesRef configNetworkInterfacePref, SCPreferencesRef expectedNetworkInterfacePref)
3885 {
3886 CFDictionaryRef expectedInterfaceEntity = NULL;
3887 CFArrayRef expectedInterfaceList = NULL;
3888 CFIndex expectedInterfaceListCount;
3889 Boolean foundMatch = FALSE;
3890 CFDictionaryRef interfaceEntity = NULL;
3891 CFArrayRef interfaceList = NULL;
3892 CFIndex interfaceListCount;
3893 CFMutableArrayRef interfaceListMutable = NULL;
3894 Boolean success = FALSE;
3895
3896 interfaceList = SCPreferencesGetValue(configNetworkInterfacePref, INTERFACES);
3897 if (!isA_CFArray(interfaceList)) {
3898 goto done;
3899 }
3900 interfaceListMutable = CFArrayCreateMutableCopy(NULL, 0, interfaceList);
3901 interfaceListCount = CFArrayGetCount(interfaceListMutable);
3902
3903 expectedInterfaceList = SCPreferencesGetValue(expectedNetworkInterfacePref, INTERFACES);
3904 if (!isA_CFArray(expectedInterfaceList)) {
3905 goto done;
3906 }
3907 expectedInterfaceListCount = CFArrayGetCount(expectedInterfaceList);
3908
3909 if (interfaceListCount != expectedInterfaceListCount) {
3910 goto done;
3911 }
3912
3913 for (CFIndex idx = 0; idx < expectedInterfaceListCount; idx++) {
3914 foundMatch = FALSE;
3915 expectedInterfaceEntity = CFArrayGetValueAtIndex(expectedInterfaceList, idx);
3916 interfaceListCount = CFArrayGetCount(interfaceListMutable);
3917
3918 for (CFIndex idx2 = 0; idx2 < interfaceListCount; idx2++) {
3919 interfaceEntity = CFArrayGetValueAtIndex(interfaceList, idx2);
3920 if (CFEqual(expectedInterfaceEntity, interfaceEntity)) {
3921 foundMatch = TRUE;
3922 break;
3923 }
3924 }
3925 if (!foundMatch) {
3926 break;
3927 }
3928 }
3929 success = foundMatch;
3930
3931 done:
3932 if (interfaceListMutable != NULL) {
3933 CFRelease(interfaceListMutable);
3934 }
3935
3936 return success;
3937 }
3938
3939 Boolean
3940 _SCNetworkMigrationAreConfigurationsIdentical (CFURLRef configurationURL,
3941 CFURLRef expectedConfigurationURL)
3942 {
3943 CFURLRef baseConfigURL = NULL;
3944 CFURLRef baseExpectedConfigURL = NULL;
3945 CFURLRef configPreferencesURL = NULL;
3946 CFURLRef configNetworkInterfacesURL = NULL;
3947 SCPreferencesRef configPref = NULL;
3948 SCPreferencesRef configNetworkInterfacePref = NULL;
3949 SCPreferencesRef expectedConfigPref = NULL;
3950 SCPreferencesRef expectedNetworkInterfacePref = NULL;
3951 CFURLRef expectedNetworkInterfaceURL = NULL;
3952 CFURLRef expectedPreferencesURL = NULL;
3953 Boolean isIdentical = FALSE;
3954 CFStringRef networkInterfaceConfigString = NULL;
3955 CFStringRef networkInterfaceExpectedString = NULL;
3956 CFStringRef prefsConfigString = NULL;
3957 CFStringRef prefsExpectedString = NULL;
3958 char networkInterfaceConfigStr[PATH_MAX];
3959 char networkInterfaceExpectedStr[PATH_MAX];
3960 char prefsConfigStr[PATH_MAX];
3961 char prefsExpectedStr[PATH_MAX];
3962
3963 if (configurationURL == NULL ||
3964 expectedConfigurationURL == NULL) {
3965 return FALSE;
3966 }
3967 baseConfigURL = CFURLCreateWithFileSystemPathRelativeToBase(NULL,
3968 PREFS_DEFAULT_DIR_RELATIVE,
3969 kCFURLPOSIXPathStyle,
3970 TRUE,
3971 configurationURL);
3972 configPreferencesURL = CFURLCreateFromFileSystemRepresentationRelativeToBase(NULL,
3973 (const UInt8*)PREFS_DEFAULT_CONFIG_PLIST,
3974 sizeof(PREFS_DEFAULT_CONFIG_PLIST),
3975 FALSE,
3976 baseConfigURL);
3977 if (!CFURLResourceIsReachable(configPreferencesURL, NULL)) {
3978 SC_log(LOG_NOTICE, "No preferences.plist file: %@", configPreferencesURL);
3979 goto done;
3980 }
3981
3982 configNetworkInterfacesURL = CFURLCreateFromFileSystemRepresentationRelativeToBase(NULL,
3983 (const UInt8*)INTERFACES_DEFAULT_CONFIG_PLIST,
3984 sizeof(INTERFACES_DEFAULT_CONFIG_PLIST),
3985 FALSE,
3986 baseConfigURL);
3987 if (!CFURLResourceIsReachable(configNetworkInterfacesURL, NULL)) {
3988 SC_log(LOG_NOTICE, "No NetworkInterfaces.plist file: %@", configNetworkInterfacesURL);
3989 goto done;
3990 }
3991
3992 if (!CFURLGetFileSystemRepresentation(configPreferencesURL, TRUE, (UInt8*)prefsConfigStr, sizeof(prefsConfigStr))) {
3993 SC_log(LOG_NOTICE, "Cannot get file system representation for url: %@", configPreferencesURL);
3994 goto done;
3995 }
3996 if (!CFURLGetFileSystemRepresentation(configNetworkInterfacesURL, TRUE, (UInt8*)networkInterfaceConfigStr, sizeof(networkInterfaceConfigStr))) {
3997 SC_log(LOG_NOTICE, "Cannot get file system representation for url: %@", configNetworkInterfacesURL);
3998 goto done;
3999 }
4000
4001 baseExpectedConfigURL = CFURLCreateWithFileSystemPathRelativeToBase(NULL,
4002 PREFS_DEFAULT_DIR_RELATIVE,
4003 kCFURLPOSIXPathStyle,
4004 TRUE,
4005 expectedConfigurationURL);
4006 expectedPreferencesURL = CFURLCreateFromFileSystemRepresentationRelativeToBase(NULL,
4007 (const UInt8*)PREFS_DEFAULT_CONFIG_PLIST,
4008 sizeof(PREFS_DEFAULT_CONFIG_PLIST),
4009 FALSE,
4010 baseExpectedConfigURL);
4011
4012 if (!CFURLResourceIsReachable(expectedPreferencesURL, NULL)) {
4013 SC_log(LOG_NOTICE, "No expected preferences.plist file");
4014 goto done;
4015 }
4016
4017 expectedNetworkInterfaceURL = CFURLCreateFromFileSystemRepresentationRelativeToBase(NULL,
4018 (const UInt8*)INTERFACES_DEFAULT_CONFIG_PLIST,
4019 sizeof(INTERFACES_DEFAULT_CONFIG_PLIST),
4020 FALSE,
4021 baseExpectedConfigURL);
4022
4023 if (!CFURLResourceIsReachable(expectedNetworkInterfaceURL, NULL)) {
4024 SC_log(LOG_NOTICE, "No expected NetworkInterfaces.plist file");
4025 goto done;
4026 }
4027
4028 if (!CFURLGetFileSystemRepresentation(expectedPreferencesURL, TRUE, (UInt8*)prefsExpectedStr, sizeof(prefsExpectedStr))) {
4029 SC_log(LOG_NOTICE, "Cannot get file system representation for url: %@", expectedPreferencesURL);
4030 goto done;
4031 }
4032 if (!CFURLGetFileSystemRepresentation(expectedNetworkInterfaceURL, TRUE, (UInt8*)networkInterfaceExpectedStr, sizeof(networkInterfaceExpectedStr))) {
4033 SC_log(LOG_NOTICE, "Cannot get file system representation for url: %@", expectedNetworkInterfaceURL);
4034 goto done;
4035 }
4036
4037 prefsConfigString = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), prefsConfigStr);
4038 networkInterfaceConfigString = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), networkInterfaceConfigStr);
4039 prefsExpectedString = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), prefsExpectedStr);
4040 networkInterfaceExpectedString = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), networkInterfaceExpectedStr);
4041
4042 configPref = SCPreferencesCreate(NULL, PLUGIN_ID, prefsConfigString);
4043 expectedConfigPref = SCPreferencesCreate(NULL, PLUGIN_ID, prefsExpectedString);
4044 configNetworkInterfacePref = SCPreferencesCreate(NULL, PLUGIN_ID, networkInterfaceConfigString);
4045 expectedNetworkInterfacePref = SCPreferencesCreate(NULL, PLUGIN_ID, networkInterfaceExpectedString);
4046 done:
4047 if (configPref == NULL ||
4048 expectedConfigPref == NULL ||
4049 configNetworkInterfacePref == NULL ||
4050 expectedNetworkInterfacePref == NULL) {
4051 SC_log(LOG_NOTICE, "One of the preferences is NULL");
4052 isIdentical = FALSE;
4053 } else {
4054 isIdentical = (_SCNetworkMigrationAreServicesIdentical(configPref, expectedConfigPref) &&
4055 _SCNetworkMigrationAreNetworkInterfaceConfigurationsIdentical(configNetworkInterfacePref, expectedNetworkInterfacePref));
4056 }
4057 if (baseConfigURL != NULL) {
4058 CFRelease(baseConfigURL);
4059 }
4060 if (configPreferencesURL != NULL) {
4061 CFRelease(configPreferencesURL);
4062 }
4063 if (configNetworkInterfacesURL != NULL) {
4064 CFRelease(configNetworkInterfacesURL);
4065 }
4066 if (baseExpectedConfigURL != NULL) {
4067 CFRelease(baseExpectedConfigURL);
4068 }
4069 if (expectedPreferencesURL != NULL) {
4070 CFRelease(expectedPreferencesURL);
4071 }
4072 if (expectedNetworkInterfaceURL != NULL) {
4073 CFRelease(expectedNetworkInterfaceURL);
4074 }
4075 if (prefsConfigString != NULL) {
4076 CFRelease(prefsConfigString);
4077 }
4078 if (networkInterfaceConfigString != NULL) {
4079 CFRelease(networkInterfaceConfigString);
4080 }
4081 if (prefsExpectedString != NULL) {
4082 CFRelease(prefsExpectedString);
4083 }
4084 if (networkInterfaceExpectedString != NULL) {
4085 CFRelease(networkInterfaceExpectedString);
4086 }
4087 if (configPref != NULL) {
4088 CFRelease(configPref);
4089 }
4090 if (expectedConfigPref != NULL) {
4091 CFRelease(expectedConfigPref);
4092 }
4093 if (configNetworkInterfacePref != NULL) {
4094 CFRelease(configNetworkInterfacePref);
4095 }
4096 if (expectedNetworkInterfacePref != NULL) {
4097 CFRelease(expectedNetworkInterfacePref);
4098 }
4099 return isIdentical;
4100 }
4101
4102 CFArrayRef
4103 _SCNetworkConfigurationCopyMigrationRemovePaths (CFArrayRef targetPaths,
4104 CFURLRef targetDir)
4105 {
4106 CFURLRef affectedURL;
4107 char filePath[PATH_MAX];
4108 CFURLRef targetFile;
4109 CFMutableArrayRef toBeRemoved = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
4110
4111 for (CFIndex idx = 0; idx < CFArrayGetCount(targetPaths); idx++) {
4112 affectedURL = CFArrayGetValueAtIndex(targetPaths, idx);
4113
4114 if (!CFURLGetFileSystemRepresentation(affectedURL, TRUE, (UInt8*)filePath, sizeof(filePath))) {
4115 SC_log(LOG_NOTICE, "Cannot get file system representation for url: %@", affectedURL);
4116 continue;
4117 }
4118 targetFile = CFURLCreateFromFileSystemRepresentationRelativeToBase(NULL,
4119 (const UInt8*)filePath,
4120 strnlen(filePath, sizeof(filePath)),
4121 FALSE,
4122 targetDir);
4123
4124 if (!CFURLResourceIsReachable(targetFile, NULL)) {
4125 CFArrayAppendValue(toBeRemoved, affectedURL);
4126 }
4127 CFRelease(targetFile);
4128 }
4129 // If number of files to be removed is 0, return NULL
4130 if (CFArrayGetCount(toBeRemoved) == 0) {
4131 CFRelease(toBeRemoved);
4132 toBeRemoved = NULL;
4133 }
4134 return toBeRemoved;
4135 }