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