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