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