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