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