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