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