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