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