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