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