SCNetworkMigration.c   [plain text]


/*
 * Copyright (c) 2014 Apple Inc. All rights reserved.
 *
 * @APPLE_LICENSE_HEADER_START@
 * 
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Apple Public Source License
 * Version 2.0 (the 'License'). You may not use this file except in
 * compliance with the License. Please obtain a copy of the License at
 * http://www.opensource.apple.com/apsl/ and read it before using this
 * file.
 * 
 * The Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 * Please see the License for the specific language governing rights and
 * limitations under the License.
 * 
 * @APPLE_LICENSE_HEADER_END@
 */

//
//  SCNetworkMigration.c
//
//  Created by Ashish Kulkarni on 11/19/13.
//
//

#include <stdio.h>
#include <CoreFoundation/CoreFoundation.h>
#include <SystemConfiguration/SystemConfiguration.h>
#include <SystemConfiguration/SCNetworkConfigurationPrivate.h>
#include <SystemConfiguration/SCNetworkConfigurationInternal.h>
#include "SCPreferencesInternal.h"
#include <IOKit/network/IONetworkInterface.h>
#include <IOKit/network/IONetworkController.h>
#include <SystemConfiguration/SCPrivate.h>
#include <sys/stat.h>
#include <copyfile.h>
#include <sys/param.h>
#include <pthread.h>

#define BACK_TO_MY_MAC			CFSTR("BackToMyMac")
#define BACK_TO_MY_MAC_DSIDS		CFSTR("BackToMyMacDSIDs")
#define	PREFS_DEFAULT_DIR_PLIST		"/Library/Preferences/SystemConfiguration"
#define PREFS_DEFAULT_DIR_RELATIVE	CFSTR("Library/Preferences/SystemConfiguration/")
#define	PREFS_DEFAULT_CONFIG_PLIST	"preferences.plist"
#define	NETWORK_INTERFACES_PREFS_PLIST	"NetworkInterfaces.plist"
#define NUM_MIGRATION_PATHS		2
#define PLUGIN_ID			CFSTR("System Migration")
#define PREFERENCES_PLIST_INDEX		0
#define NETWORK_INTERFACES_PLIST_INDEX	1


const CFStringRef kSCNetworkConfigurationMigrationActionKey = CFSTR("MigrationActionKey");
const CFStringRef kSCNetworkConfigurationRepair = CFSTR("ConfigurationRepair");
#if	!TARGET_OS_IPHONE
static CFDictionaryRef
_SCNetworkMigrationCopyMappingBSDNameToBridgeServices(SCPreferencesRef prefs);

static CFDictionaryRef
_SCNetworkMigrationCopyMappingBSDNameToBondServices(SCPreferencesRef prefs);

static CFDictionaryRef
_SCNetworkMigrationCopyMappingBSDNameToVLANServices(SCPreferencesRef prefs);
#endif
static Boolean
_SCNetworkConfigurationIsInterfaceNamerMappable(SCNetworkInterfaceRef interface1, SCNetworkInterfaceRef interface2, Boolean bypassActive);

static Boolean
_SCNetworkConfigurationMigrateConfiguration(CFURLRef sourceDir, CFURLRef targetDir);

static void
_SCNetworkConfigurationCopyMigrationPathsWithBaseURL(CFURLRef baseURL, CFURLRef *prefs, CFURLRef *interfaces)
{
	if (baseURL != NULL) {
		CFRetain(baseURL);
	}
	else {
		baseURL = CFURLCreateFromFileSystemRepresentation(NULL,
								  (UInt8*)PREFS_DEFAULT_DIR_PLIST,
								  sizeof(PREFS_DEFAULT_DIR_PLIST),
								  TRUE);
	}

	*prefs = CFURLCreateFromFileSystemRepresentationRelativeToBase(NULL,
								      (UInt8*)PREFS_DEFAULT_CONFIG_PLIST,
								      sizeof(PREFS_DEFAULT_CONFIG_PLIST) - 1,
								      FALSE, baseURL);

	*interfaces = CFURLCreateFromFileSystemRepresentationRelativeToBase(NULL,
									   (UInt8*)NETWORK_INTERFACES_PREFS_PLIST,
									   sizeof(NETWORK_INTERFACES_PREFS_PLIST) - 1,
									   FALSE, baseURL);
	CFRelease(baseURL);
	return;
}

CFArrayRef
_SCNetworkConfigurationCopyMigrationPaths(CFDictionaryRef options)
{
	CFURLRef interfaces;
	CFMutableArrayRef migrationPaths = NULL;
	CFURLRef prefs;
	
	if (getenv(INSTALL_ENVIRONMENT) != NULL) {
		_sc_debug = 1;
	}
	_SCNetworkConfigurationCopyMigrationPathsWithBaseURL(NULL, &prefs, &interfaces);

	migrationPaths = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
	CFArrayInsertValueAtIndex(migrationPaths, PREFERENCES_PLIST_INDEX, prefs);
	CFArrayInsertValueAtIndex(migrationPaths, NETWORK_INTERFACES_PLIST_INDEX, interfaces);

	CFRelease(prefs);
	CFRelease(interfaces);
	return migrationPaths;
}

static Boolean
_SCNetworkConfigurationRemoveConfigurationFiles(CFURLRef configDir)
{
	
	char configPathString[PATH_MAX];
	CFURLRef configPathURL = NULL;
	char configNetworkInterfacesPathString[PATH_MAX];
	CFURLRef configNetworkInterfacesPathURL = NULL;
	
	_SCNetworkConfigurationCopyMigrationPathsWithBaseURL(configDir, &configPathURL, &configNetworkInterfacesPathURL);
	
	if(CFURLGetFileSystemRepresentation(configPathURL, TRUE, (UInt8*)configPathString, sizeof(configPathString)) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationRemoveConfigurationFiles: configPathString is NULL"));
	}
	else {
		if (remove(configPathString) != 0) {
			SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationRemoveConfigurationFiles: Removing file failed from: %s. Error is %d"), configPathString, errno);
		}
	}
	
	if(CFURLGetFileSystemRepresentation(configNetworkInterfacesPathURL, TRUE, (UInt8*)configNetworkInterfacesPathString, sizeof(configNetworkInterfacesPathString)) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationRemoveConfigurationFiles: configNetwork"));
	}
	else {
		if (remove(configNetworkInterfacesPathString) != 0) {
			SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationRemoveConfigurationFiles: Removing file failed from: %s. Error is %d"), configNetworkInterfacesPathString, errno);
		}
	}
	
	if (configPathURL != NULL) {
		CFRelease(configPathURL);
	}
	if (configNetworkInterfacesPathURL != NULL) {
		CFRelease(configNetworkInterfacesPathURL);
	}
	
	return TRUE;
}

static Boolean
SCNetworkConfigurationCopyConfigurationFiles(CFURLRef	configDir,
					     CFURLRef	targetDir)      // TargetDir needs to exist
{
	errno_t error;
	mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
	char networkInterfacesPathString[PATH_MAX];
	CFURLRef networkInterfacesPathURL = NULL;
	copyfile_state_t networkInterfacesState;
	char preferencesPathString[PATH_MAX];
	CFURLRef preferencesPathURL = NULL;
	Boolean removeTargetFiles = FALSE;
	copyfile_state_t state;
	Boolean success = FALSE;
	char targetNetworkInterfacesPathString[PATH_MAX];
	CFURLRef targetNetworkInterfacesPathURL = NULL;
	char targetPathString[PATH_MAX];
	CFURLRef targetPathURL = NULL;

	_SCNetworkConfigurationCopyMigrationPathsWithBaseURL(targetDir, &targetPathURL, &targetNetworkInterfacesPathURL);
	
	if (CFURLGetFileSystemRepresentation(targetPathURL, TRUE, (UInt8*)targetPathString, sizeof(targetPathString)) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("SCNetworkConfigurationCopyConfigurationFiles: targetPathString is NULL"));
		goto done;
	}
	
	if (CFURLGetFileSystemRepresentation(targetNetworkInterfacesPathURL, TRUE, (UInt8*)targetNetworkInterfacesPathString, sizeof(targetNetworkInterfacesPathString)) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("SCNetworkConfigurationCopyConfigurationFiles: targetNetworkInterfacesPathString is NULL"));
		goto done;
	}
	
	if (configDir == NULL) {
		removeTargetFiles = TRUE;
		success = TRUE;
		goto done;
	}
	_SCNetworkConfigurationCopyMigrationPathsWithBaseURL(configDir, &preferencesPathURL, &networkInterfacesPathURL);

	if (CFURLGetFileSystemRepresentation(preferencesPathURL, TRUE, (UInt8*)preferencesPathString, sizeof(preferencesPathString)) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("SCNetworkConfigurationCopyConfigurationFiles: preferencesPathString is NULL"));
		goto done;
	}


	if (CFURLGetFileSystemRepresentation(networkInterfacesPathURL, TRUE, (UInt8*)networkInterfacesPathString, sizeof(networkInterfacesPathString)) == FALSE) {
		SCLog(_sc_debug, LOG_DEBUG, CFSTR("SCNetworkConfigurationCopyConfigurationFiles: networkInterfacePathString is NULL"));
		goto done;
	}
	
	state = copyfile_state_alloc();
	if ((error = copyfile(preferencesPathString, targetPathString, state, COPYFILE_ALL)) != 0) {
		SCLog(TRUE, LOG_ERR, CFSTR("SCNetworkConfigurationCopyConfigurationFiles: Copying failed from:%s to %s. Error is %d"), preferencesPathString, targetPathString, errno);
		copyfile_state_free(state);
		removeTargetFiles = TRUE;
		goto done;
	}
	copyfile_state_free(state);
	chmod(targetPathString, mode);

	networkInterfacesState = copyfile_state_alloc();
	if ((error = copyfile(networkInterfacesPathString, targetNetworkInterfacesPathString, networkInterfacesState, COPYFILE_ALL)) != 0) {
		SCLog(TRUE, LOG_ERR, CFSTR("SCNetworkConfigurationCopyConfigurationFiles: Copying failed from:%s to %s. Error is %d"), networkInterfacesPathString, targetNetworkInterfacesPathString, errno);
		copyfile_state_free(networkInterfacesState);
		removeTargetFiles = TRUE;
		goto done;
	}
	copyfile_state_free(networkInterfacesState);
	chmod(targetNetworkInterfacesPathString, mode);

	success = TRUE;
done:
	if (removeTargetFiles == TRUE) {
		_SCNetworkConfigurationRemoveConfigurationFiles(targetDir);
	}
	if (preferencesPathURL != NULL) {
		CFRelease(preferencesPathURL);
	}
	if (networkInterfacesPathURL != NULL) {
		CFRelease(networkInterfacesPathURL);
	}
	if (targetPathURL != NULL) {
		CFRelease(targetPathURL);
	}
	if (targetNetworkInterfacesPathURL != NULL) {
		CFRelease(targetNetworkInterfacesPathURL);
	}
	return success;
}


/* -----------------------------------------------------------------------------
 Create directories and intermediate directories as required.
 ----------------------------------------------------------------------------- */
static Boolean
_SCNetworkConfigurationMakePathIfNeeded(CFURLRef pathURL)
{
	char    *c;
	mode_t  newmask;
	char	path[PATH_MAX];
	char    thepath[PATH_MAX];
	CFIndex slen=0;
	struct stat sb;
	Boolean success = FALSE;

	if (CFURLGetFileSystemRepresentation(pathURL, TRUE, (UInt8 *)path, sizeof(path)) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationMakePathIfNeeded: Could not get character array from target string"));
		return success;
	}
	SCLog(TRUE, LOG_NOTICE, CFSTR("_SCNetworkConfigurationMakePathIfNeeded: Creating path: %s"), path);
	
	newmask = S_IRWXU | S_IRGRP | S_IROTH | S_IXGRP | S_IXOTH;

	slen = strlen(path);

	strlcpy( thepath, path, slen+1);
	c = thepath;
	if ( *c == '/' )
		c++;
	for(  ; !success; c++){
		if ( (*c == '/') || ( *c == '\0' )){
			if ( *c == '\0' )
				success = TRUE;
			else
				*c = '\0';
			if ( mkdir( thepath, newmask) ){
				if ( errno == EEXIST || errno == EISDIR){
					if ( stat(thepath, &sb) < 0){
						printf("stat returned value < 0\n");
						break;
					}
				} else {
					printf("received error: %s\n", strerror(errno));
					break;
				}
			}
			*c = '/';
		}
	}
	return success;
}

static SCPreferencesRef
__SCNetworkCreateDefaultPref(CFStringRef prefsID)
{
	SCPreferencesRef prefs;
	SCNetworkSetRef currentSet;
	CFStringRef model;
	
	prefs = SCPreferencesCreate(NULL, PLUGIN_ID, prefsID);
	if (prefs == NULL) {
		return NULL;
	}
	
	currentSet = SCNetworkSetCopyCurrent(prefs);
	if (currentSet == NULL) {
		CFBundleRef bundle;
		CFStringRef setName = NULL;
		
		currentSet = SCNetworkSetCreate(prefs);
		bundle = _SC_CFBundleGet();
		if (bundle != NULL) {
			setName = CFBundleCopyLocalizedString(bundle,
							      CFSTR("DEFAULT_SET_NAME"),
							      CFSTR("Automatic"),
							      NULL);
		}
		SCNetworkSetSetName(currentSet, (setName != NULL) ? setName : CFSTR("Automatic"));
		SCNetworkSetSetCurrent(currentSet);
		if (setName != NULL) {
			CFRelease(setName);
		}
	}
	SCNetworkSetEstablishDefaultConfiguration(currentSet);
	CFRelease(currentSet);
	
	model = SCPreferencesGetValue(prefs, MODEL);
	if (model == NULL) {
		model = _SC_hw_model(FALSE);
		SCPreferencesSetValue(prefs, MODEL, model);
	}
	
	return prefs;
}

__private_extern__
SCPreferencesRef
__SCNetworkCreateDefaultNIPrefs(CFStringRef prefsID)
{
	CFMutableArrayRef interfaces = NULL;
	CFStringRef model;
	CFArrayRef networkInterfaces;
	SCPreferencesRef ni_prefs;
	CFComparisonResult res;
	
	
	networkInterfaces = __SCNetworkInterfaceCopyAll_IONetworkInterface();
	
	if (networkInterfaces == NULL) {
		return NULL;
	}
	if (prefsID == NULL) {
		prefsID = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@/%@"), PREFS_DEFAULT_DIR, NETWORK_INTERFACES_PREFS);
	}
	else {
		CFRetain(prefsID);
	}
	
	ni_prefs = SCPreferencesCreate(NULL, PLUGIN_ID , prefsID);
	CFRelease(prefsID);
	
	if (ni_prefs == NULL) {
		goto done;
	}
	
	interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
	
	for (CFIndex idx = 0; idx < CFArrayGetCount(networkInterfaces); idx++) {
		CFIndex idx2 = 0;
		CFNumberRef if_type;
		CFNumberRef if_unit;
		SCNetworkInterfaceRef interface = CFArrayGetValueAtIndex(networkInterfaces, idx);
		CFDictionaryRef interfaceEntity = __SCNetworkInterfaceCopyStorageEntity(interface);
		
		if (interfaceEntity == NULL) {
			continue;
		}
		
		if_type = _SCNetworkInterfaceGetIOInterfaceType(interface);
		if_unit = _SCNetworkInterfaceGetIOInterfaceUnit(interface);
		
		if ((if_type == NULL) || (if_unit == NULL)) {
			CFRelease(interfaceEntity);
			continue;
		}
		
		for (idx2 = 0; idx2 < CFArrayGetCount(interfaces); idx2++) {
			CFNumberRef db_type;
			CFNumberRef db_unit;
			CFDictionaryRef dict = CFArrayGetValueAtIndex(interfaces, idx2);
			
			db_type = CFDictionaryGetValue(dict, CFSTR(kIOInterfaceType));
			db_unit = CFDictionaryGetValue(dict, CFSTR(kIOInterfaceUnit));
			res = CFNumberCompare(if_type, db_type, NULL);
			if (res == kCFCompareLessThan
			|| (res == kCFCompareEqualTo
			&& (CFNumberCompare(if_unit, db_unit, NULL) == kCFCompareLessThan))) {
				break;
			}
		}
		
		CFArrayInsertValueAtIndex(interfaces, idx2, interfaceEntity);
		CFRelease(interfaceEntity);
		
	}
	SCPreferencesSetValue(ni_prefs, INTERFACES, interfaces);
	
	model = SCPreferencesGetValue(ni_prefs, MODEL);
	if (model == NULL) {
		model = _SC_hw_model(FALSE);
		SCPreferencesSetValue(ni_prefs, MODEL, model);
	}
done:
	if (interfaces != NULL) {
		CFRelease(interfaces);
	}
	if (networkInterfaces != NULL) {
		CFRelease(networkInterfaces);
	}
	
	return ni_prefs;
}


/*
 *  _SCNetworkConfigurationPerformMigration will migrate configuration between source and destination systems
 */
CF_RETURNS_RETAINED
CFArrayRef
_SCNetworkConfigurationPerformMigration(CFURLRef sourceDir, CFURLRef currentDir, CFURLRef targetDir, CFDictionaryRef options)
{
	CFURLRef currentDirConfig = NULL;
	CFURLRef currentSystemPath = NULL;
	Boolean migrationComplete = FALSE;
	CFArrayRef paths = NULL;
	Boolean removeTargetOnFailure = FALSE;
	CFURLRef sourceDirConfig = NULL;
	CFURLRef targetDirConfig = NULL;
	
	if (getenv(INSTALL_ENVIRONMENT) != NULL) {
		_sc_debug = 1;
	}

	// Both sourceDir and currentDir cannot be NULL because NULL value indicates using current system
	if (sourceDir == NULL && currentDir == NULL) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationPerformMigration: Both sourceDir and currentDir are NULL"));
		goto done;
	}

	currentSystemPath = CFURLCreateWithString(NULL,
						  PREFS_DEFAULT_DIR,
						  NULL);

	// if either of the sourceDir or currentDir are NULL, then populate it with current system path
	if (sourceDir == NULL) {
		sourceDirConfig = CFRetain(currentSystemPath);
	}
	else {
		sourceDirConfig = CFURLCreateWithFileSystemPathRelativeToBase(NULL, PREFS_DEFAULT_DIR_RELATIVE, kCFURLPOSIXPathStyle, TRUE, sourceDir);
	}

	if (currentDir != NULL) {
		currentDirConfig = CFURLCreateWithFileSystemPathRelativeToBase(NULL, PREFS_DEFAULT_DIR_RELATIVE, kCFURLPOSIXPathStyle, TRUE, currentDir);
	}
	// If the targetDir is not provided then migration will take place in currentDir
	if (targetDir == NULL) {
		targetDirConfig = CFRetain(currentSystemPath);
	}
	else {
		targetDirConfig = CFURLCreateWithFileSystemPathRelativeToBase(NULL, PREFS_DEFAULT_DIR_RELATIVE, kCFURLPOSIXPathStyle, TRUE, targetDir);
	}
	// Source directory cannot be the same as Target Directory
	if (CFEqual(sourceDirConfig, targetDirConfig)) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationPerformMigration: Source directory cannot be the same as target directory"));
		goto done;
	}
	
	if ((currentDirConfig == NULL) || (CFEqual(currentDirConfig, targetDirConfig) == FALSE)) {
		if (_SCNetworkConfigurationMakePathIfNeeded(targetDirConfig) == FALSE) {
			SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationPerformMigration: Could not create target directory as expected"));
			goto done;
		}

		if (SCNetworkConfigurationCopyConfigurationFiles(currentDirConfig, targetDirConfig) == FALSE) {
			SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationPerformMigration: Could not copy configuration files from %@ to %@"),
			      currentDirConfig, targetDirConfig);
		}
		else if (currentDirConfig != NULL) {
			removeTargetOnFailure = TRUE;	// Configuration files were copied over to target directory
							// If migration failed, then we should remove those configuration
							// files since current directory and target directory are not
							// the same
		}
	}

	// If both source and current configurations point to current system, then no migration needs to be done.
	if ((currentDirConfig != NULL) && (CFEqual(sourceDirConfig, currentDirConfig) == TRUE)) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationPerformMigration:  both source and current configurations point to same path ... No migration needs to be done"));
		migrationComplete = TRUE;
	}
	else {
		migrationComplete = _SCNetworkConfigurationMigrateConfiguration(sourceDirConfig, targetDirConfig);
	}
	SCLog(TRUE, LOG_NOTICE, CFSTR("Migration %s"), migrationComplete ? "complete" : "failed");
	if (migrationComplete == TRUE) {
		paths = _SCNetworkConfigurationCopyMigrationPaths(NULL);
	}
	else {
		// If migration fails, then remove configuration files from target config if they are
		// copied from the current directory
		if (removeTargetOnFailure == TRUE) {
			_SCNetworkConfigurationRemoveConfigurationFiles(targetDirConfig);
		}
	}
done:
	if (currentDirConfig != NULL) {
		CFRelease(currentDirConfig);
	}
	if (currentSystemPath != NULL) {
		CFRelease(currentSystemPath);
	}
	if (sourceDirConfig != NULL) {
		CFRelease(sourceDirConfig);
	}
	if (targetDirConfig != NULL) {
		CFRelease(targetDirConfig);
	}
	return paths;
}

static Boolean
_SCNetworkConfigurationMigrateIsFilePresent(CFURLRef filePath)
{
	Boolean fileExists = false;
	char filePathStr[PATH_MAX];
	int statResult = 0;
	struct stat statStruct = {0, };

	if (filePath == NULL) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationMigrateIsFilePresent: filePath is NULL"));
		goto done;
	}

	if (CFURLGetFileSystemRepresentation(filePath, TRUE, (UInt8*) filePathStr, sizeof(filePathStr)) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationMigrateIsFilePresent: Couldn't get file system representation\n"));
		goto done;
	}

	statResult = stat(filePathStr, &statStruct);

	if (statResult == 0) {
		fileExists = TRUE;
	}
done:
	return fileExists;
}

static Boolean
__SCNetworkConfigurationMigrateConfigurationFilesPresent(CFURLRef baseURL, CFArrayRef* migrationPaths)
{
	Boolean configFilesPresent = FALSE;
	CFIndex count;
	CFURLRef filePath = NULL;
	CFURLRef interfaces;
	CFMutableArrayRef migrationPathsMutable = NULL;
	CFURLRef prefs;

	if (baseURL == NULL) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("__SCNetworkConfigurationMigrateConfigurationFilesPresent: baseURL is NULL"));
		goto done;
	}

	_SCNetworkConfigurationCopyMigrationPathsWithBaseURL(baseURL, &prefs, &interfaces);

	migrationPathsMutable = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
	CFArrayInsertValueAtIndex(migrationPathsMutable, PREFERENCES_PLIST_INDEX, prefs);
	CFArrayInsertValueAtIndex(migrationPathsMutable, NETWORK_INTERFACES_PLIST_INDEX, interfaces);

	CFRelease(prefs);
	CFRelease(interfaces);

	*migrationPaths = migrationPathsMutable;

	if ((*migrationPaths == NULL) ||
	    ((count = CFArrayGetCount(*migrationPaths)) == 0)) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("__SCNetworkConfigurationMigrateConfigurationFilesPresent: migrationPath is NULL or number of elements in migrationPath array is 0"));
		goto done;
	}

	for (CFIndex idx = 0; idx < count; idx++) {
		filePath = CFArrayGetValueAtIndex(*migrationPaths, idx);
		if (_SCNetworkConfigurationMigrateIsFilePresent(filePath) ==  FALSE) {
			SCLog(_sc_debug, LOG_NOTICE, CFSTR("__SCNetworkConfigurationMigrateConfigurationFilesPresent: File not present: %@"), filePath);
			goto done;
		}
	}

	configFilesPresent = TRUE;	// all necessary configuration files present
done:
	return configFilesPresent;
}


static CFMutableArrayRef
_SCNetworkInterfaceCopyInterfacesFilteredByBuiltinWithPreferences     (SCPreferencesRef   ni_prefs, Boolean isBuiltin)
{
	CFIndex count = 0;
	SCNetworkInterfaceRef interface;
	CFArrayRef interfaceList = NULL;
	CFMutableArrayRef resultInterfaceList = NULL;

	interfaceList = __SCNetworkInterfaceCopyStoredWithPreferences(ni_prefs);
	if (interfaceList == NULL) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkInterfaceCopyInterfacesFilteredByBuiltinWithPreferences: interfaceList is NULL"));
		goto done;
	}

	count = CFArrayGetCount(interfaceList);
	if (count > 0) {
		resultInterfaceList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
	}

	for (CFIndex i = 0; i < count; i++) {
		interface = CFArrayGetValueAtIndex(interfaceList, i);

		if (_SCNetworkInterfaceIsBuiltin(interface) == isBuiltin) {
			CFArrayAppendValue(resultInterfaceList, interface);
		}
	}

done:
	if (interfaceList != NULL) {
		CFRelease(interfaceList);
	}
	return resultInterfaceList;
}

static CFMutableDictionaryRef
_SCNetworkInterfaceStorageCopyMaxUnitPerInterfaceType(SCPreferencesRef ni_prefs)
{
	CFNumberRef cfMaxUnit;
	CFIndex count = 0;
	CFArrayRef ifList = NULL;
	SCNetworkInterfaceRef interface;
	CFMutableDictionaryRef InterfaceTypeToMaxUnitMapping = NULL;
	CFNumberRef type;
	CFNumberRef unit;

	ifList = __SCNetworkInterfaceCopyStoredWithPreferences(ni_prefs);

	if (ifList == NULL) {
		SCLog(TRUE, LOG_ERR, CFSTR("_SCNetworkInterfaceStorageCopyMaxUnitPerInterfaceType: ifList is NULL"));
		return 0;
	}

	InterfaceTypeToMaxUnitMapping = CFDictionaryCreateMutable(NULL, 0,
								    &kCFTypeDictionaryKeyCallBacks,
								    &kCFTypeDictionaryValueCallBacks);
	count = CFArrayGetCount(ifList);

	for (CFIndex idx = 0; idx < count; idx++) {
		cfMaxUnit = NULL;
		interface = CFArrayGetValueAtIndex(ifList, idx);

		if (isA_SCNetworkInterface(interface) == NULL) {
			continue;
		}

		type  = _SCNetworkInterfaceGetIOInterfaceType(interface);

		if (isA_CFNumber(type) == NULL) {
			SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkInterfaceStorageCopyMaxUnitPerInterfaceType: type is NULL"));
			continue;
		}

		if (CFDictionaryContainsKey(InterfaceTypeToMaxUnitMapping, type) == FALSE) {
			int temp = 0;
			cfMaxUnit = CFNumberCreate(NULL, kCFNumberIntType, &temp);
			CFDictionaryAddValue(InterfaceTypeToMaxUnitMapping, type, cfMaxUnit);
			CFRelease(cfMaxUnit);
		}

		if (cfMaxUnit == NULL) {
			cfMaxUnit = CFDictionaryGetValue(InterfaceTypeToMaxUnitMapping, type);
		}

		unit = _SCNetworkInterfaceGetIOInterfaceUnit(interface);

		if (isA_CFNumber(unit) == NULL) {
			continue;
		}

		if (CFNumberCompare(unit, cfMaxUnit, NULL) == kCFCompareGreaterThan) {
			CFDictionarySetValue(InterfaceTypeToMaxUnitMapping, type, unit);
		}
	}
	if (ifList != NULL) {
		CFRelease(ifList);
	}
	return InterfaceTypeToMaxUnitMapping;
}

static CFMutableDictionaryRef
_SCNetworkConfigurationCopyBuiltinMapping (SCPreferencesRef sourcePrefs, SCPreferencesRef targetPrefs)
{
	CFMutableDictionaryRef builtinMapping = NULL;
	CFIndex sourceBuiltinInterfaceCount = 0;
	CFMutableArrayRef sourceBuiltinInterfaces = NULL;
	SCNetworkInterfaceRef sourceInterface;
	CFIndex targetBuiltinInterfaceCount = 0;
	CFMutableArrayRef targetBuiltinInterfaces = NULL;
	SCNetworkInterfaceRef targetInterface;

	sourceBuiltinInterfaces = _SCNetworkInterfaceCopyInterfacesFilteredByBuiltinWithPreferences(sourcePrefs, TRUE);
	if (isA_CFArray(sourceBuiltinInterfaces) == NULL) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationCopyBuiltinMapping: sourceBuiltinInterfaces is NULL"));
		goto done;
	}
	sourceBuiltinInterfaceCount = CFArrayGetCount(sourceBuiltinInterfaces);

	targetBuiltinInterfaces = _SCNetworkInterfaceCopyInterfacesFilteredByBuiltinWithPreferences(targetPrefs, TRUE);
	if (isA_CFArray(targetBuiltinInterfaces) == NULL) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationCopyBuiltinMapping: targetBuiltinInterfaces is NULL"));
		goto done;
	}
	targetBuiltinInterfaceCount = CFArrayGetCount(targetBuiltinInterfaces);

	// Builtin Mapping will try to map all source interfaces into target interfaces
	for (CFIndex idx = 0; idx < sourceBuiltinInterfaceCount; idx++) {
		sourceInterface = CFArrayGetValueAtIndex(sourceBuiltinInterfaces, idx);
		for (CFIndex idx2 = 0; idx2 < targetBuiltinInterfaceCount; idx2++) {
			targetInterface = CFArrayGetValueAtIndex(targetBuiltinInterfaces, idx2);

			if (_SCNetworkConfigurationIsInterfaceNamerMappable(sourceInterface, targetInterface, FALSE) == TRUE) {
				if (builtinMapping == NULL) {
					builtinMapping = CFDictionaryCreateMutable(NULL, 0,
										   &kCFTypeDictionaryKeyCallBacks,
										   &kCFTypeDictionaryValueCallBacks);
				}
				CFDictionaryAddValue(builtinMapping, sourceInterface, targetInterface);
				CFArrayRemoveValueAtIndex(targetBuiltinInterfaces, idx2);
				break;
			}
		}
		targetBuiltinInterfaceCount = CFArrayGetCount(targetBuiltinInterfaces);
	}

done:
	if (sourceBuiltinInterfaces != NULL) {
		CFRelease(sourceBuiltinInterfaces);
	}
	if (targetBuiltinInterfaces != NULL) {
		CFRelease(targetBuiltinInterfaces);
	}
	return builtinMapping;
}

static CFMutableDictionaryRef
_SCNetworkConfigurationCopyExternalInterfaceMapping (SCPreferencesRef sourcePref, SCPreferencesRef targetPrefs)
{
	CFNumberRef cfMaxTargetUnit = NULL;
	CFNumberRef currentInterfaceUnit = NULL;
	CFMutableDictionaryRef externalMapping = NULL;
	CFMutableDictionaryRef InterfaceTypeToMaxUnitMapping = NULL;
	int maxTargetUnit;
	int newTargetUnit;
	CFIndex sourceExternalInterfaceCount = 0;
	CFMutableArrayRef sourceExternalInterfaces = NULL;
	SCNetworkInterfaceRef sourceInterface = NULL;
	CFIndex targetExternalInterfaceCount = 0;
	CFMutableArrayRef targetExternalInterfaces = NULL;
	SCNetworkInterfaceRef targetInterface = NULL;
	CFNumberRef type;

	sourceExternalInterfaces = _SCNetworkInterfaceCopyInterfacesFilteredByBuiltinWithPreferences(sourcePref, FALSE);
	if (isA_CFArray(sourceExternalInterfaces) == NULL) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationCopyExternalInterfaceMapping: sourceExternalInterfaces is NULL"));
		goto done;
	}
	sourceExternalInterfaceCount = CFArrayGetCount(sourceExternalInterfaces);

	if (sourceExternalInterfaceCount == 0) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationCopyExternalInterfaceMapping: sourceExternalInterfaceCount is 0"));
		goto done;
	}

	targetExternalInterfaces = _SCNetworkInterfaceCopyInterfacesFilteredByBuiltinWithPreferences(targetPrefs, FALSE);
	if (isA_CFArray(targetExternalInterfaces) == NULL) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationCopyExternalInterfaceMapping: targetExternalInterfaces is NULL"));
		goto done;
	}

	InterfaceTypeToMaxUnitMapping = _SCNetworkInterfaceStorageCopyMaxUnitPerInterfaceType(targetPrefs);
	externalMapping = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);

	// Map all external interfaces which exist in both source and target
	for (CFIndex idx = 0; idx < sourceExternalInterfaceCount; idx++) {
		sourceInterface = CFArrayGetValueAtIndex(sourceExternalInterfaces, idx);
		targetExternalInterfaceCount = CFArrayGetCount(targetExternalInterfaces);
		currentInterfaceUnit = NULL;

		for (CFIndex idx2 = 0; idx2 < targetExternalInterfaceCount; idx2++) {
			targetInterface = CFArrayGetValueAtIndex(targetExternalInterfaces, idx2);

			if (_SCNetworkConfigurationIsInterfaceNamerMappable(sourceInterface, targetInterface, TRUE) == TRUE) {
				CFDictionaryAddValue(externalMapping, sourceInterface, targetInterface);
				CFArrayRemoveValueAtIndex(targetExternalInterfaces, idx2);
				break;
			}
		}

		if (CFDictionaryContainsKey(externalMapping, sourceInterface) == FALSE) {
			// Create new mappings for external source interfaces which don't exist in the target
			type = _SCNetworkInterfaceGetIOInterfaceType(sourceInterface);

			cfMaxTargetUnit = CFDictionaryGetValue(InterfaceTypeToMaxUnitMapping, type);
			if (cfMaxTargetUnit != NULL) {
				CFNumberGetValue(cfMaxTargetUnit, kCFNumberIntType, &maxTargetUnit);
				newTargetUnit = maxTargetUnit + 1;
			}
			else {
				newTargetUnit = 0;
			}

			cfMaxTargetUnit = CFNumberCreate(NULL, kCFNumberIntType, &newTargetUnit);
			CFDictionarySetValue(InterfaceTypeToMaxUnitMapping, type, cfMaxTargetUnit);

			targetInterface = (SCNetworkInterfaceRef)__SCNetworkInterfaceCreateCopy(NULL, sourceInterface, NULL, NULL);

			SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationCopyExternalInterfaceMapping: sourceInterface: %p, target Interface: %p"), sourceInterface, targetInterface);

			currentInterfaceUnit = _SCNetworkInterfaceGetIOInterfaceUnit(targetInterface);

			if ((isA_CFNumber(currentInterfaceUnit) == NULL) ||
			    (CFEqual(currentInterfaceUnit, cfMaxTargetUnit) == FALSE)) {
				// Update the interface unit
				__SCNetworkInterfaceSetIOInterfaceUnit(targetInterface, cfMaxTargetUnit);
			}

			CFDictionaryAddValue(externalMapping, sourceInterface, targetInterface);

			CFRelease(targetInterface);
			targetInterface = NULL;
			CFRelease(cfMaxTargetUnit);
			cfMaxTargetUnit = NULL;
		}
	}
done:
	if (sourceExternalInterfaces != NULL) {
		CFRelease(sourceExternalInterfaces);
	}
	if (targetExternalInterfaces != NULL) {
		CFRelease(targetExternalInterfaces);
	}
	if (InterfaceTypeToMaxUnitMapping != NULL) {
		CFRelease(InterfaceTypeToMaxUnitMapping);
	}
	return externalMapping;
}
static Boolean
__SCNetworkConfigurationInterfaceNameIsEquiv(CFStringRef interfaceName1, CFStringRef interfaceName2);

static Boolean
_SCNetworkConfigurationIsInterfaceNamerMappable(SCNetworkInterfaceRef interface1, SCNetworkInterfaceRef interface2, Boolean bypassActive)
{
	Boolean interface1IsBuiltin;
	CFStringRef interface1Prefix;
	CFStringRef interface1Type;
	CFStringRef interface1UserDefinedName;
	Boolean interface2IsBuiltin;
	CFStringRef interface2Prefix;
	CFStringRef interface2Type;
	CFStringRef interface2UserDefinedName;

	if (interface1 == interface2) {
		// No work needs to be done
		return TRUE;
	}
	interface1IsBuiltin = _SCNetworkInterfaceIsBuiltin(interface1);
	interface2IsBuiltin = _SCNetworkInterfaceIsBuiltin(interface2);

	interface1UserDefinedName = SCNetworkInterfaceGetLocalizedDisplayName(interface1);
	interface2UserDefinedName = SCNetworkInterfaceGetLocalizedDisplayName(interface2);

	interface1Type = SCNetworkInterfaceGetInterfaceType(interface1);
	interface2Type = SCNetworkInterfaceGetInterfaceType(interface2);

	interface1Prefix = _SCNetworkInterfaceGetIOInterfaceNamePrefix(interface1);
	interface2Prefix = _SCNetworkInterfaceGetIOInterfaceNamePrefix(interface2);

	// Check if have same builtin values.
	// Check if User Defined name matches
	// Check if SCNetwork Interface Type matches

	if (interface1IsBuiltin != interface2IsBuiltin) {
		return FALSE;
	}

	if (_SC_CFEqual(interface1Type, interface2Type) == FALSE) {
		return FALSE;
	}

	if (_SC_CFEqual(interface1Prefix, interface2Prefix) == FALSE) {
		return FALSE;
	}

	if (_SC_CFEqual(interface1UserDefinedName, interface2UserDefinedName) == FALSE) {
		// Checking if we have a mismatch because of the name Ethernet and Ethernet 1
		// Checking if we have a mismatch because of the name Airport and WiFi
		if ((interface1IsBuiltin == TRUE) &&
		    (interface2IsBuiltin == TRUE) &&
		    (__SCNetworkConfigurationInterfaceNameIsEquiv(interface1UserDefinedName, interface2UserDefinedName) == TRUE)) {
			    return TRUE;
		}
		return FALSE;
	}
	return TRUE;
}

static Boolean
__SCNetworkConfigurationInterfaceNameIsEquiv(CFStringRef interfaceName1, CFStringRef interfaceName2)
{
	CFStringRef interfaceArray[] = { CFSTR("iPhone"), CFSTR("iPad"), CFSTR("iPod"), CFSTR("AppleTV") };
	const int interfaceCount = sizeof(interfaceArray) / sizeof(CFStringRef);
	CFStringRef portSuffix = CFSTR(", Port 1");
	
	if ((isA_CFString(interfaceName1) != NULL) &&
	    (isA_CFString(interfaceName2) != NULL)) {
		if (CFEqual(interfaceName1, interfaceName2) == FALSE) {
			// Check if we are looking at the WiFi interface
			if ((CFEqual(interfaceName1, CFSTR("AirPort")) ||
			     (CFEqual(interfaceName1, CFSTR("Wi-Fi")))) &&
			    (CFEqual(interfaceName2, CFSTR("AirPort")) ||
			     (CFEqual(interfaceName2, CFSTR("Wi-Fi"))))) {
				return TRUE;
			}
			
			if (((CFEqual(interfaceName1, CFSTR("Ethernet"))) ||
			     (CFEqual(interfaceName1, CFSTR("Ethernet 1")))) &&
			    ((CFEqual(interfaceName2, CFSTR("Ethernet"))) ||
			     (CFEqual(interfaceName2, CFSTR("Ethernet 1"))))) {
				return TRUE;
			}
			
			if (((CFStringHasSuffix(interfaceName1, portSuffix) == TRUE) &&
			    (CFStringCompareWithOptions(interfaceName1, interfaceName2, CFRangeMake(0, (CFStringGetLength(interfaceName1) - CFStringGetLength(portSuffix))), 0) == kCFCompareEqualTo)) ||
			    ((CFStringHasSuffix(interfaceName2, portSuffix) == TRUE) &&
			     (CFStringCompareWithOptions(interfaceName2, interfaceName1, CFRangeMake(0, (CFStringGetLength(interfaceName2) - CFStringGetLength(portSuffix))), 0) == kCFCompareEqualTo))) {
				return TRUE;
			}
			
			for (CFIndex idx = 0; idx < interfaceCount; idx++) {
				CFStringRef tempInterfaceName = interfaceArray[idx];
				if ((CFEqual(interfaceName1, tempInterfaceName) == TRUE ||
					__SCNetworkInterfaceMatchesName(interfaceName1, tempInterfaceName) == TRUE) &&
				    (CFEqual(interfaceName2, tempInterfaceName) == TRUE  ||
					__SCNetworkInterfaceMatchesName(interfaceName2, tempInterfaceName) == TRUE)) {
					return TRUE;
				}
			}
		}
		else {
			return TRUE;
		}
	}
	
	return FALSE;
}

typedef struct {
	CFDictionaryRef interfaceMapping;
	CFMutableArrayRef interfacesMissingServices;
} SCNetworkConfigurationMissingServiceContext;

typedef struct {
	CFDictionaryRef bsdNameToBridgeServices;	// Mapping of BSD Name to SCBridgeInterfaceRef
	CFDictionaryRef bsdNameToBondServices;		// Mapping of BSD Name to SCBondInterfaceRef
	CFDictionaryRef bsdNameToVLANServices;		// Mapping of BSD Name to SCVLANInterfaceRef
	CFDictionaryRef interfaceMapping;
	Boolean* isValid;
	CFMutableArrayRef interfaceToBeRemoved;	// SCNetworkInterfaceRef. Services containing the interface will be removed
	CFMutableArrayRef interfaceToBeReplaced;// SCNetworkInterfaceRef. Services containing the interface will be replaced with default service
	Boolean repair;
} SCNetworkConfigurationValidityContext;

static void
_SCNetworkConfigurationValidateInterface (const void *key, const void *value, void *context)
{
	CFStringRef bsdName = (CFStringRef)key;
	SCNetworkConfigurationValidityContext *ctx = (SCNetworkConfigurationValidityContext*)context;
	CFDictionaryRef bsdNameToBridgeServices = ctx->bsdNameToBridgeServices;
	CFDictionaryRef bsdNameToBondServices = ctx->bsdNameToBondServices;
	CFDictionaryRef bsdNameToVLANServices = ctx->bsdNameToVLANServices;
	SCNetworkInterfaceRef interface = NULL;
	CFDictionaryRef interfaceMapping = ctx->interfaceMapping;
	CFStringRef interfaceUserDefinedName = NULL;
	Boolean repair = ctx->repair;
	SCNetworkInterfaceRef serviceInterface = (SCNetworkInterfaceRef)value;
	CFStringRef serviceInterfaceUserDefinedName = NULL;
	CFMutableArrayRef interfaceToBeRemoved = ctx->interfaceToBeRemoved;
	CFMutableArrayRef interfaceToBeReplaced = ctx->interfaceToBeReplaced;
	
	// No work needs to be done if we have already made determination that configuration somewhere is not valid,
	// or we don't intend to repair invalid configuration.
	if ((*ctx->isValid == FALSE) && (repair == FALSE)) {
		return;
	}

	// There is no interface present for the service
	interface = CFDictionaryGetValue(interfaceMapping, bsdName);
	if (interface == NULL) {
		if ((((bsdNameToBridgeServices != NULL) && (CFDictionaryContainsKey(bsdNameToBridgeServices, bsdName) == FALSE))) &&
		    (((bsdNameToBondServices != NULL) && (CFDictionaryContainsKey(bsdNameToBondServices, bsdName) == FALSE))) &&
		    (((bsdNameToVLANServices != NULL) && (CFDictionaryContainsKey(bsdNameToVLANServices, bsdName) == FALSE)))) {
			// Not a virtual interface
			SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationValidateInterface: There is no real interface with bsd name: %@ for service"), bsdName);
			
			if (repair == TRUE) {
				CFArrayAppendValue(interfaceToBeRemoved, serviceInterface);
			}
			*ctx->isValid = FALSE;
		}
		return;
	}

	// TODO: Need to compare between both SCNetworkInterfaceRefs
	interfaceUserDefinedName = __SCNetworkInterfaceGetUserDefinedName(interface);
	serviceInterfaceUserDefinedName = __SCNetworkInterfaceGetUserDefinedName(serviceInterface);

	if (__SCNetworkConfigurationInterfaceNameIsEquiv(interfaceUserDefinedName, serviceInterfaceUserDefinedName) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationValidateInterface: Interface user defined name: %@ doesn't match service interface user defined name: %@"), interfaceUserDefinedName, serviceInterfaceUserDefinedName);
		*ctx->isValid = FALSE;
		// Add service interface to the interfaceToBeReplaced list
		if (isA_CFArray(interfaceToBeReplaced) != NULL) {
			CFArrayAppendValue(interfaceToBeReplaced, interface);
		}
		if (isA_CFArray(interfaceToBeRemoved) != NULL) {
			CFArrayAppendValue(interfaceToBeRemoved, serviceInterface);
		}
		return;
	}
}

static void
_SCNetworkConfigurationCollectMissingService(const void *key, const void *value, void *context)
{
	CFStringRef bsdName = (CFStringRef)key;
	SCNetworkConfigurationMissingServiceContext *ctx = (SCNetworkConfigurationMissingServiceContext*)context;
	SCNetworkInterfaceRef interface = (SCNetworkInterfaceRef)value;
	CFMutableArrayRef interfacesMissingServices = ctx->interfacesMissingServices;
	CFDictionaryRef serviceInterfaceMapping = ctx->interfaceMapping;

	if ((isA_SCNetworkInterface(interface) == NULL) ||
	    (_SCNetworkInterfaceIsBuiltin(interface) == FALSE)) {
		return;
	}

	// Check if services have mapping for the BSD name of the interface
	if (CFDictionaryContainsKey(serviceInterfaceMapping, bsdName) == FALSE) {
		CFArrayAppendValue(interfacesMissingServices, interface); // Adding interface since the corresponding service seems to be missing
	}
}

static Boolean
_SCNetworkConfigurationCreateBuiltinInterfaceServices(SCPreferencesRef pref,
						      SCPreferencesRef ni_pref)
{
	SCNetworkConfigurationMissingServiceContext context;
	SCNetworkInterfaceRef interface = NULL;
	CFArrayRef interfaces = NULL;
	CFMutableArrayRef interfacesWithoutService = NULL;
	CFDictionaryRef mappingBSDNameToInterface = NULL;
	CFDictionaryRef mappingServiceBSDNameToInterface = NULL;
	CFIndex missingServiceCount = 0;
	Boolean success = FALSE;

	interfaces = __SCNetworkInterfaceCopyStoredWithPreferences(ni_pref);
	if (interfaces == NULL) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationCreateBuiltinInterfaceServices: interfaces is NULL or not of the correct type"));
		goto done;
	}

	mappingBSDNameToInterface = __SCNetworkInterfaceCreateMappingUsingBSDName(interfaces);
	CFRelease(interfaces);
	if (isA_CFDictionary(mappingBSDNameToInterface) == NULL) {
		goto done;
	}

	interfaces = __SCNetworkServiceCopyAllInterfaces(pref);
	if (interfaces == NULL) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationCreateBuiltinInterfaceServices: interfaces is NULL for configPref or not of the correct type"));
		goto done;
	}
	mappingServiceBSDNameToInterface = __SCNetworkInterfaceCreateMappingUsingBSDName(interfaces);
	CFRelease(interfaces);
	if (isA_CFDictionary(mappingServiceBSDNameToInterface) == NULL) {
		goto done;
	}

	interfacesWithoutService = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);

	context.interfaceMapping = mappingServiceBSDNameToInterface;
	context.interfacesMissingServices = interfacesWithoutService;

	CFDictionaryApplyFunction(mappingBSDNameToInterface, _SCNetworkConfigurationCollectMissingService, &context);
	missingServiceCount = CFArrayGetCount(interfacesWithoutService);

	success = TRUE;

	for (CFIndex idx = 0; idx < missingServiceCount; idx++) {
		interface = CFArrayGetValueAtIndex(interfacesWithoutService, idx);

		if (__SCNetworkServiceCreate(pref, interface, NULL) == FALSE) {
			SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationCreateBuiltinInterfaceServices: Could not add service for interface: %@"), interface);
			success = FALSE;
		}
	}
done:
	if (mappingBSDNameToInterface != NULL) {
		CFRelease(mappingBSDNameToInterface);
	}
	if (mappingServiceBSDNameToInterface != NULL) {
		CFRelease(mappingServiceBSDNameToInterface);
	}
	if (interfacesWithoutService != NULL) {
		CFRelease(interfacesWithoutService);
	}

	return success;
}

static void
add_default_service(const void *value, void *context)
{
	SCNetworkSetRef currentSet = NULL;
	SCNetworkInterfaceRef interface = (SCNetworkInterfaceRef)value;
	SCPreferencesRef prefs = (SCPreferencesRef)context;
	SCNetworkServiceRef service;
	
	service = SCNetworkServiceCreate(prefs, interface);
	
	if (service == NULL) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("add_default_service: Could not create new service"));
		goto done;
	}
	
	if (SCNetworkServiceEstablishDefaultConfiguration(service) == FALSE) {
		SCNetworkServiceRemove(service);
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("add_default_service: SCNetworkServiceEstablishDefaultConfiguration failed"));
		goto done;
	}
	
	// Add Service to current set
	currentSet = SCNetworkSetCopyCurrent(prefs);
	if (currentSet == NULL) {
		SCNetworkServiceRemove(service);
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("add_default_service: Could not find current set"));
		goto done;
	}
	
	if (SCNetworkSetAddService(currentSet, service) == FALSE) {
		SCNetworkServiceRemove(service);
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("add_default_service: Could not add service to current set"));
		goto done;
	}
done:
	if (service != NULL) {
		CFRelease(service);
	}
	if (currentSet != NULL) {
		CFRelease(currentSet);
	}
}

static void
remove_service(const void *value, void *context)
{
	SCNetworkInterfaceRef interface;
	SCNetworkServiceRef service = (SCNetworkServiceRef)value;
	CFArrayRef toBeRemoved = (CFArrayRef)context;
	
	interface = SCNetworkServiceGetInterface(service);
	
	if (CFArrayContainsValue(toBeRemoved, CFRangeMake(0, CFArrayGetCount(toBeRemoved)), interface)) {
		SCNetworkServiceRemove(service);
	}
}

static void
_SCNetworkConfigurationSaveOldConfiguration(SCPreferencesRef prefs)
{
	CFAbsoluteTime absoluteTime;
	CFCalendarRef currentCalendar;
	int day;
	int hour;
	CFStringRef keyList[] = {
			kSCPrefCurrentSet,
			MODEL,
			kSCPrefNetworkServices,
			kSCPrefSets,
			kSCPrefSystem,
			kSCPrefVirtualNetworkInterfaces
	};
	CFIndex keyListCount;
	int minute;
	int month;
	int second;
	int year;
	
	currentCalendar = CFCalendarCopyCurrent();
	absoluteTime = CFAbsoluteTimeGetCurrent();
	
	if (CFCalendarDecomposeAbsoluteTime(currentCalendar, absoluteTime, "yMdHms",
					    &year, &month, &day, &hour, &minute, &second) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationSaveOldConfiguration: Cannot decompose absolute time"));
	}
	keyListCount = (CFIndex)sizeof(keyList)/sizeof(CFStringRef);
	
	for (CFIndex idx = 0; idx < keyListCount; idx++) {
		CFStringRef newKey;
		CFTypeRef value = SCPreferencesGetValue(prefs, keyList[idx]);
		
		if (value != NULL) {
			newKey = CFStringCreateWithFormat(NULL, NULL,
							  CFSTR("%d-%d-%d %d:%d:%d : %@"),
							  year, month, day, hour,
							  minute, second, keyList[idx]);
			SCPreferencesSetValue(prefs, newKey, value);
			CFRelease(newKey);
		}
	}
	CFRelease(currentCalendar);
}

static Boolean
_SCNetworkConfigurationRepairUsingPreferences(SCPreferencesRef prefs,
					      CFArrayRef interfaceToBeRemoved,
					      CFArrayRef interfaceToBeReplaced)
{
	CFIndex removeCount;
	CFIndex replaceCount;
	CFArrayRef serviceList;
	
	removeCount = CFArrayGetCount(interfaceToBeRemoved);
	replaceCount = CFArrayGetCount(interfaceToBeReplaced);
	if (removeCount == 0 &&
	    replaceCount == 0) {
		// We don't have any information to repair
		return FALSE;
	}
	// Backup current preferences before making changes
	_SCNetworkConfigurationSaveOldConfiguration(prefs);
	
	serviceList = SCNetworkServiceCopyAll(prefs);
	CFArrayApplyFunction(serviceList, CFRangeMake(0, CFArrayGetCount(serviceList)), remove_service, (void*)interfaceToBeRemoved);
	
	CFArrayApplyFunction(interfaceToBeReplaced, CFRangeMake(0, replaceCount), add_default_service, (void*)prefs);
	CFRelease(serviceList);
	return TRUE;
}

static void
validate_bridge(const void *value, void *context)
{
	SCBridgeInterfaceRef bridge = (SCBridgeInterfaceRef) value;
	CFArrayRef memberInterfaces = SCBridgeInterfaceGetMemberInterfaces(bridge);
	CFMutableArrayRef memberInterfacesMutable = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
	SCPreferencesRef ni_prefs = (SCPreferencesRef)context;
	
	for (CFIndex idx = 0; idx < CFArrayGetCount(memberInterfaces); idx++) {
		CFStringRef bsdName;
		SCNetworkInterfaceRef interface = (SCNetworkInterfaceRef)CFArrayGetValueAtIndex(memberInterfaces, idx);
		SCNetworkInterfaceRef memberInterface;
		
		bsdName = SCNetworkInterfaceGetBSDName(interface);
		if (bsdName == NULL) {
			continue;
		}
		
		// Check if member interface is present
		memberInterface = __SCNetworkInterfaceCreateWithNIPreferencesUsingBSDName(NULL, ni_prefs, bsdName);
		if (memberInterface != NULL) {
			CFArrayAppendValue(memberInterfacesMutable, memberInterface);
			CFRelease(memberInterface);
		}
	}
	
	if (CFArrayGetCount(memberInterfacesMutable) == 0) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("validate_bridge: Removing invalid bridge configuration: %@"), bridge);
		SCBridgeInterfaceRemove(bridge);
	}
	else {
		SCBridgeInterfaceSetMemberInterfaces(bridge, memberInterfacesMutable);
	}
	CFRelease(memberInterfacesMutable);
}
#if	!TARGET_OS_IPHONE
static void
validate_bond(const void *value, void *context)
{
	SCBondInterfaceRef bond = (SCBondInterfaceRef)value;
	CFArrayRef memberInterfaces = SCBondInterfaceGetMemberInterfaces(bond);
	CFMutableArrayRef memberInterfacesMutable = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
	SCPreferencesRef ni_prefs = (SCPreferencesRef)context;
	
	for (CFIndex idx = 0; idx < CFArrayGetCount(memberInterfaces); idx++) {
		CFStringRef bsdName;
		SCNetworkInterfaceRef interface = (SCNetworkInterfaceRef)CFArrayGetValueAtIndex(memberInterfaces, idx);
		SCNetworkInterfaceRef memberInterface;
		
		bsdName = SCNetworkInterfaceGetBSDName(interface);
		if (bsdName == NULL) {
			continue;
		}
		
		// Check if member interface is present
		memberInterface = __SCNetworkInterfaceCreateWithNIPreferencesUsingBSDName(NULL, ni_prefs, bsdName);
		if (memberInterface != NULL) {
			CFArrayAppendValue(memberInterfacesMutable, memberInterface);
			CFRelease(memberInterface);
		}
	}
	
	if (CFArrayGetCount(memberInterfacesMutable) == 0) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("validate_bond: Removing invalid bond configuration: %@"), bond);
		SCBondInterfaceRemove(bond);
	}
	else {
		SCBondInterfaceSetMemberInterfaces(bond, memberInterfacesMutable);
	}
	CFRelease(memberInterfacesMutable);
}
#endif

static void
validate_vlan(const void *value, void *context)
{
	CFStringRef bsdName;
	SCNetworkInterfaceRef interface;
	Boolean isValid = TRUE;
	SCPreferencesRef ni_prefs = (SCPreferencesRef)context;
	SCNetworkInterfaceRef physicalInterface;
	SCVLANInterfaceRef vlan = (SCVLANInterfaceRef)value;
	
	physicalInterface = SCVLANInterfaceGetPhysicalInterface(vlan);
	bsdName = SCNetworkInterfaceGetBSDName(physicalInterface);
	
	if (bsdName == NULL) {
		isValid = FALSE;
		goto done;
	}
	
	// Check if the physical interface is present
	interface = __SCNetworkInterfaceCreateWithNIPreferencesUsingBSDName(NULL, ni_prefs, bsdName);
	if (interface == NULL) {
		isValid = FALSE;
		goto done;
	}
	CFRelease(interface);
	
done:
	if (isValid == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("validate_vlan: Removing invalid VLAN configuration: %@"), vlan);
		SCVLANInterfaceRemove(vlan);
	}
}

static Boolean
_SCNetworkConfigurationCheckValidityUsingPreferences(SCPreferencesRef prefs,
						     SCPreferencesRef ni_prefs,
						     CFDictionaryRef options)
{
	CFArrayRef allServices = NULL;
	CFArrayRef allSets = NULL;
	CFDictionaryRef bsdNameToBridgeServices = NULL;
	CFDictionaryRef bsdNameToBondServices = NULL;
	CFDictionaryRef bsdNameToVLANServices = NULL;
	SCNetworkConfigurationValidityContext context;
	CFArrayRef interfaces = NULL;
	Boolean isValid = TRUE;
	CFDictionaryRef mappingBSDNameToInterface = NULL;
	CFDictionaryRef mappingServiceBSDNameToInterface = NULL;
	Boolean repairConfiguration = FALSE;
	CFArrayRef setServiceOrder = NULL;
	CFArrayRef setServices = NULL;
	CFMutableArrayRef interfaceToBeRemoved = NULL;
	CFMutableArrayRef interfaceToBeReplaced = NULL;
	
	
	if  ((isA_CFDictionary(options) != NULL)) {
		CFBooleanRef repair = CFDictionaryGetValue(options, kSCNetworkConfigurationRepair);
		if (isA_CFBoolean(repair) != NULL) {
			repairConfiguration = CFBooleanGetValue(repair);
		}
	}

	/*
	 Check the validity by:
	 1) Comparing if the interfaces names mentioned in NetworkInterfaces.plist and preferences.plist match
	 Use the functions
	 CFDictionaryRef
	 __SCNetworkInterfaceCreateMappingUsingBSDName(SCPreferencesRef prefs);
	 */
	interfaces = __SCNetworkInterfaceCopyStoredWithPreferences(ni_prefs);
	if (isA_CFArray(interfaces) == NULL) {
		isValid = FALSE;
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationCheckValidityUsingPreferences: interfaces is NULL or not of the correct type"));
		goto done;
	}
	mappingBSDNameToInterface = __SCNetworkInterfaceCreateMappingUsingBSDName(interfaces);
	CFRelease(interfaces);
	if (isA_CFDictionary(mappingBSDNameToInterface) == NULL) {
		isValid = FALSE;
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationCheckValidityUsingPreferences: mappingBSDNameToInterface is NULL"));
		goto done;
	}

	interfaces = __SCNetworkServiceCopyAllInterfaces(prefs);
	if (isA_CFArray(interfaces) == NULL) {
		isValid = FALSE;
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationCheckValidityUsingPreferences: interfaces is NULL for configPref or not of the correct type"));
		goto done;
	}
	mappingServiceBSDNameToInterface = __SCNetworkInterfaceCreateMappingUsingBSDName(interfaces);
	CFRelease(interfaces);
	if (isA_CFDictionary(mappingServiceBSDNameToInterface) == NULL) {
		isValid = FALSE;
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationCheckValidityUsingPreferences: mappingServiceBSDNameToInterface is NULL"));
		goto done;
	}

	if (repairConfiguration) {
		interfaceToBeRemoved = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
		interfaceToBeReplaced = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
#if	!TARGET_OS_IPHONE
		bsdNameToBridgeServices = _SCNetworkMigrationCopyMappingBSDNameToBridgeServices(prefs);
		bsdNameToBondServices = _SCNetworkMigrationCopyMappingBSDNameToBondServices(prefs);
		bsdNameToVLANServices = _SCNetworkMigrationCopyMappingBSDNameToVLANServices(prefs);
#endif
	}
	context.interfaceMapping = mappingBSDNameToInterface;
	context.isValid = &isValid;
	context.interfaceToBeRemoved = interfaceToBeRemoved;
	context.interfaceToBeReplaced = interfaceToBeReplaced;
	context.bsdNameToBridgeServices = bsdNameToBridgeServices;
	context.bsdNameToBondServices = bsdNameToBondServices;
	context.bsdNameToVLANServices = bsdNameToVLANServices;
	context.repair = repairConfiguration;

	CFDictionaryApplyFunction(mappingServiceBSDNameToInterface, _SCNetworkConfigurationValidateInterface, &context);

	if (isValid == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationCheckValidityUsingPreferences: Found mismatch between interface names in NetworkInterfaces.plist and preferences.plist"));
		if (repairConfiguration) {
			isValid = _SCNetworkConfigurationRepairUsingPreferences(prefs, interfaceToBeRemoved, interfaceToBeReplaced);
			if (isValid == FALSE) {
				goto done;
			}
			// Save the changes if repair fixed an invalid configuration
			if (SCPreferencesCommitChanges(prefs) == FALSE) {
				SCLog(_sc_debug, LOG_NOTICE, CFSTR("Failed to commit changes from the repaired configuration"));
			}
		}
		else {
			goto done;
		}
	}
	/*

	 2) Check if all the network services mentioned in the SCNetworkSet are actually present in the SCNetworkService array
	 */

	allServices = SCNetworkServiceCopyAll(prefs);
	if (isA_CFArray(allServices) == NULL) {
		isValid = FALSE;
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationCheckValidityUsingPreferences: allServices is NULL"));
		goto done;
	}

	allSets = SCNetworkSetCopyAll(prefs);
	if (isA_CFArray(allSets) == NULL) {
		isValid = FALSE;
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationCheckValidityUsingPreferences: allSets is NULL"));
		goto done;
	}

	for (CFIndex idx = 0; ((idx < CFArrayGetCount(allSets)) && isValid); idx++) {
		SCNetworkSetRef set = CFArrayGetValueAtIndex(allSets, idx);

		if (isA_SCNetworkSet(set) == NULL) {
			SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationCheckValidityUsingPreferences: set is NULL"));
			continue;
		}
		setServices = SCNetworkSetCopyServices(set);
		if (setServices == NULL) {
			SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationCheckValidityUsingPreferences: setServices is NULL"));
			continue;
		}
		for (CFIndex idx2 = 0; idx2 < CFArrayGetCount(setServices); idx2++) {
			SCNetworkServiceRef service = CFArrayGetValueAtIndex(setServices, idx2);

			if (CFArrayContainsValue(allServices, CFRangeMake(0, CFArrayGetCount(allServices)), service) == FALSE) {
				isValid = FALSE;
				SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationCheckValidityUsingPreferences: All network services in the network set are not present in SCNetworkService array"));
				break;
			}
		}
		if (isValid == FALSE) {
			break;
		}

		/*
		 3) Check if service IDs in service order do exist in the SET
		 */
		setServiceOrder = SCNetworkSetGetServiceOrder(set);
		if (setServiceOrder != NULL) {
			for (CFIndex idx2 = 0; idx2 < CFArrayGetCount(setServiceOrder); idx2++) {
				SCNetworkServiceRef service = CFArrayGetValueAtIndex(setServiceOrder, idx2);
				if ((CFArrayContainsValue(setServiceOrder, CFRangeMake(0, CFArrayGetCount(setServiceOrder)), service) == FALSE) &&
				    (CFArrayContainsValue(allServices, CFRangeMake(0, CFArrayGetCount(allServices)), service) == FALSE)) {
					SCLog(_sc_debug, LOG_NOTICE, CFSTR("Service: %@ is not present in the service order for set %@"), service, set);
					break;
				}
			}
		}
		if (setServices != NULL) {
			CFRelease(setServices);
			setServices = NULL;
		}
	}
	
	/*
	 4) Check if the virtual network interfaces have valid member interfaces
	 */
	CFArrayRef bridges = SCBridgeInterfaceCopyAll(prefs);
	if (bridges != NULL) {
		CFArrayApplyFunction(bridges, CFRangeMake(0, CFArrayGetCount(bridges)), validate_bridge, (void*)ni_prefs);
		CFRelease(bridges);
	}
#if	!TARGET_OS_IPHONE
	CFArrayRef bonds = SCBondInterfaceCopyAll(prefs);
	if (bonds != NULL) {
		CFArrayApplyFunction(bonds, CFRangeMake(0, CFArrayGetCount(bonds)), validate_bond, (void*)ni_prefs);
		CFRelease(bonds);
	}
#endif
	CFArrayRef vlans = SCVLANInterfaceCopyAll(prefs);
	if (vlans != NULL) {
		CFArrayApplyFunction(vlans, CFRangeMake(0, CFArrayGetCount(vlans)), validate_vlan, (void*)ni_prefs);
		CFRelease(vlans);
	}


done:
	if (mappingBSDNameToInterface != NULL) {
		CFRelease(mappingBSDNameToInterface);
	}
	if (mappingServiceBSDNameToInterface != NULL) {
		CFRelease(mappingServiceBSDNameToInterface);
	}
	if (allServices != NULL) {
		CFRelease(allServices);
	}
	if (allSets != NULL) {
		CFRelease(allSets);
	}
	if (bsdNameToBridgeServices != NULL) {
		CFRelease(bsdNameToBridgeServices);
	}
	if (bsdNameToBondServices != NULL) {
		CFRelease(bsdNameToBondServices);
	}
	if (bsdNameToVLANServices != NULL) {
		CFRelease(bsdNameToVLANServices);
	}
	if (setServices != NULL) {
		CFRelease(setServices);
	}
	if (interfaceToBeRemoved != NULL) {
		CFRelease(interfaceToBeRemoved);
	}
	if (interfaceToBeReplaced != NULL) {
		CFRelease(interfaceToBeReplaced);
	}
	return isValid;
}

Boolean
_SCNetworkConfigurationCheckValidity(CFURLRef configDir, CFDictionaryRef options)
{
	CFURLRef baseURL = NULL;
	CFURLRef configNetworkInterfaceFile = NULL;
	CFStringRef configNetworkInterfaceFileString = NULL;
	SCPreferencesRef configNetworkInterfacePref = NULL;
	SCPreferencesRef configPref = NULL;
	CFURLRef configPreferenceFile = NULL;
	CFStringRef configPreferencesFileString = NULL;
	CFArrayRef configurationFiles = NULL;
	Boolean isValid = FALSE;
	char networkInterfaceStr[PATH_MAX];
	char prefsStr[PATH_MAX];
	
	if (configDir == NULL) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationCheckValidity: Migration files not found in directory: %@"), ((configDir == NULL) ? CFSTR("NULL") : CFURLGetString(configDir)));
		goto done;
	}
	baseURL = CFURLCreateWithFileSystemPathRelativeToBase(NULL, PREFS_DEFAULT_DIR_RELATIVE,
							      kCFURLPOSIXPathStyle, TRUE, configDir);
	
	configPreferenceFile = CFURLCreateFromFileSystemRepresentationRelativeToBase(NULL, (const UInt8*)PREFS_DEFAULT_CONFIG_PLIST, sizeof(PREFS_DEFAULT_CONFIG_PLIST), FALSE, baseURL);
	configNetworkInterfaceFile = CFURLCreateFromFileSystemRepresentationRelativeToBase(NULL, (const UInt8*)NETWORK_INTERFACES_PREFS_PLIST, sizeof(NETWORK_INTERFACES_PREFS_PLIST), FALSE, baseURL);
	
	if (CFURLGetFileSystemRepresentation(configPreferenceFile, TRUE, (UInt8*)prefsStr, sizeof(prefsStr)) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationCheckValidity: Could not extract preferences information"));
		goto done;
	}
	if (CFURLGetFileSystemRepresentation(configNetworkInterfaceFile, TRUE, (UInt8*)networkInterfaceStr, sizeof(networkInterfaceStr)) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationCheckValidity: Could not extract network interface information"));
		goto done;
	}
	
	configPreferencesFileString = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), prefsStr);
	configNetworkInterfaceFileString = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), networkInterfaceStr);

	configPref = SCPreferencesCreate(NULL,
					 PLUGIN_ID,
					 configPreferencesFileString);

	configNetworkInterfacePref = SCPreferencesCreate(NULL,
							 PLUGIN_ID,
							 configNetworkInterfaceFileString);
	if ((configPref == NULL) || (configNetworkInterfacePref == NULL)) {
		goto done;
	}

	// This function compares preferences.plist and NetworkInterfaces.plist and verifies if the values are correct
	// Checking interface mismatch for validity
	isValid = _SCNetworkConfigurationCheckValidityUsingPreferences(configPref, configNetworkInterfacePref, options);

done:
	if (baseURL != NULL) {
		CFRelease(baseURL);
	}
	if (configurationFiles != NULL) {
		CFRelease(configurationFiles);
	}
	if (configPreferencesFileString != NULL) {
		CFRelease(configPreferencesFileString);
	}
	if (configNetworkInterfaceFileString != NULL) {
		CFRelease(configNetworkInterfaceFileString);
	}
	if (configPref != NULL) {
		CFRelease(configPref);
	}
	if (configNetworkInterfacePref != NULL) {
		CFRelease(configNetworkInterfacePref);
	}
	if (configPreferenceFile != NULL) {
		CFRelease(configPreferenceFile);
	}
	if (configNetworkInterfaceFile != NULL) {
		CFRelease(configNetworkInterfaceFile);
	}
	return isValid;
}


typedef struct {
	CFMutableArrayRef externalInterfaceList;
	CFMutableArrayRef networkInterfaceList;
} SCExternalMappingContext;

static void
_SCNetworkConfigurationCollectInterfaceStorageEntity(const void *key, const void *value, void *context)
{
	SCExternalMappingContext* ctx = context;
	CFDictionaryRef interface_entity = NULL;
	SCNetworkInterfaceRef targetInterface = (SCNetworkInterfaceRef)value;

	if (CFArrayContainsValue(ctx->externalInterfaceList, CFRangeMake(0, CFArrayGetCount(ctx->externalInterfaceList)), targetInterface) == TRUE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationCollectInterfaceStorageEntity: Target Interface %@ already exists, thus do no add it to NetworkInterfaces.plist"), targetInterface);
		return; // If the target interface already exists then do not add it to NetworkInterfaces.plist
	}
	interface_entity = __SCNetworkInterfaceCopyStorageEntity(targetInterface);

	if (interface_entity != NULL) {
		CFArrayAppendValue(ctx->networkInterfaceList, interface_entity);
		CFRelease(interface_entity);
	}
}

static CFArrayRef   // CFDictionaryRef
_SCNetworkMigrationCreateNetworkInterfaceArray(SCPreferencesRef ni_prefs, CFDictionaryRef externalMapping)
{
	SCExternalMappingContext context;
	CFIndex count = 0;
	CFMutableArrayRef externalInterfaceList = NULL;
	CFArrayRef if_list = NULL;
	CFDictionaryRef interface_entity = NULL;
	CFMutableArrayRef networkInterfaceList = NULL;

	if (ni_prefs == NULL) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationCreateNetworkInterfaceArray: ni_prefs are NULL"));
		return NULL;
	}

	if_list = SCPreferencesGetValue(ni_prefs, INTERFACES);

	if ((isA_CFArray(if_list) == NULL) ||
	    ((count = CFArrayGetCount(if_list)) == 0)) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationCreateNetworkInterfaceArray: if_list is NULL or interface count is 0"));
		return NULL;
	}

	networkInterfaceList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);

	// Keep the same builtin and external interfaces
	for (CFIndex idx = 0; idx < count; idx++) {
		interface_entity = CFArrayGetValueAtIndex(if_list, idx);
		if (isA_CFDictionary(interface_entity) == NULL) {
			continue;
		}
		CFArrayAppendValue(networkInterfaceList, interface_entity);
	}

	if (isA_CFDictionary(externalMapping) == NULL) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationCreateNetworkInterfaceArray: externalMapping is NULL or not of the correct type"));
		goto done;
	}
	// Add any new external interfaces found
	externalInterfaceList = _SCNetworkInterfaceCopyInterfacesFilteredByBuiltinWithPreferences(ni_prefs, FALSE);
	context.externalInterfaceList = externalInterfaceList;
	context.networkInterfaceList = networkInterfaceList;

	CFDictionaryApplyFunction(externalMapping, _SCNetworkConfigurationCollectInterfaceStorageEntity, &context);

done:
	if (externalInterfaceList != NULL) {
		CFRelease(externalInterfaceList);
	}
	return networkInterfaceList;
}

static void
SCNetworkMigrationMapSourceToTargetName(const void *key, const void *value, void *context)
{
	SCNetworkInterfaceRef interfaceKey = (SCNetworkInterfaceRef)key;
	SCNetworkInterfaceRef interfaceValue = (SCNetworkInterfaceRef)value;
	CFMutableDictionaryRef mapping = (CFMutableDictionaryRef)context;
	CFStringRef sourceBSDName = NULL;
	CFStringRef targetBSDName = NULL;

	sourceBSDName = SCNetworkInterfaceGetBSDName(interfaceKey);
	if (isA_CFString(sourceBSDName) == NULL) {
		return;
	}

	targetBSDName = SCNetworkInterfaceGetBSDName(interfaceValue);
	if (isA_CFString(targetBSDName) == NULL) {
		return;
	}

	if (CFDictionaryContainsKey(mapping, sourceBSDName) == FALSE) {
		CFDictionaryAddValue(mapping, sourceBSDName, targetBSDName);
	}
	return;
}

static CFDictionaryRef
_SCNetworkMigrationCreateBSDNameMapping(CFDictionaryRef internalMapping, CFDictionaryRef externalMapping)
{
	CFMutableDictionaryRef bsdNameMapping = CFDictionaryCreateMutable(NULL, 0,
									  &kCFTypeDictionaryKeyCallBacks,
									  &kCFTypeDictionaryValueCallBacks);

	if ((internalMapping == NULL) && externalMapping == NULL) {
		goto done;
	}
	
	if (internalMapping != NULL) {
		CFDictionaryApplyFunction(internalMapping, SCNetworkMigrationMapSourceToTargetName, bsdNameMapping);
	}

	if (externalMapping != NULL) {
		CFDictionaryApplyFunction(externalMapping, SCNetworkMigrationMapSourceToTargetName, bsdNameMapping);
	}
	
done:
	return bsdNameMapping;
}

typedef struct {
	CFMutableArrayRef mutableServiceArray;
	SCPreferencesRef prefs;
} SCNetworkServiceArrayCopyContext;

static CFDictionaryRef
_SCNetworkMigrationCreateServiceSetMapping(SCPreferencesRef prefs)
{
	CFMutableDictionaryRef serviceSetMapping = CFDictionaryCreateMutable(NULL, 0,
									     &kCFTypeDictionaryKeyCallBacks,
									     &kCFTypeDictionaryValueCallBacks);
	SCNetworkServiceRef service = NULL;
	CFArrayRef services = NULL;
	CFMutableArrayRef setList = NULL;
	CFArrayRef sets = NULL;
	
	services = SCNetworkServiceCopyAll(prefs);
	if (services == NULL) {
		goto done;
	}
	for (CFIndex idx = 0; idx < CFArrayGetCount(services); idx++) {
		service = CFArrayGetValueAtIndex(services, idx);
		
		if (CFDictionaryContainsKey(serviceSetMapping, service) == FALSE) {
			setList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
			CFDictionaryAddValue(serviceSetMapping, service, setList);
			CFRelease(setList);
		}
	}
	CFRelease(services);
	
	sets = SCNetworkSetCopyAll(prefs);
	if (sets == NULL) {
		goto done;
	}
	
	for (CFIndex idx = 0; idx < CFArrayGetCount(sets); idx++) {
		SCNetworkSetRef set = CFArrayGetValueAtIndex(sets, idx);
		services = SCNetworkSetCopyServices(set);
		
		for (CFIndex idx2 = 0; idx2 < CFArrayGetCount(services); idx2++) {
			service = CFArrayGetValueAtIndex(services, idx2);
			setList = (CFMutableArrayRef)CFDictionaryGetValue(serviceSetMapping, service);
			if (setList != NULL) {
				CFArrayAppendValue(setList, set);
			}
		}
		CFRelease(services);
	}
	
done:
	if (sets != NULL) {
		CFRelease(sets);
	}
	return serviceSetMapping;
}

static CFDictionaryRef
_SCNetworkMigrationCreateSetMapping(SCPreferencesRef sourcePrefs,
				    SCPreferencesRef targetPrefs)
{
	SCNetworkSetRef currentSourceSet = NULL;
	CFMutableDictionaryRef setMapping = NULL;
	CFStringRef setName;
	CFArrayRef sourceSets = NULL;
	CFArrayRef targetSets = NULL;
	CFMutableArrayRef targetSetsMutable = NULL;
	
	sourceSets = SCNetworkSetCopyAll(sourcePrefs);
	targetSets = SCNetworkSetCopyAll(targetPrefs);
	
	if (sourceSets == NULL ||
	    targetSets == NULL) {
		goto done;
	}
	targetSetsMutable = CFArrayCreateMutableCopy(NULL, 0, targetSets);
	
	setMapping = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
	
	currentSourceSet = SCNetworkSetCopyCurrent(sourcePrefs);
	
	for (CFIndex idx = 0; idx < CFArrayGetCount(sourceSets); idx++) {
		SCNetworkSetRef sourceSet = CFArrayGetValueAtIndex(sourceSets, idx);
		CFIndex targetCount = CFArrayGetCount(targetSetsMutable);
		SCNetworkSetRef targetSet;
		
		setName = SCNetworkSetGetName(sourceSet);
		if (targetCount > 0) {
			targetSet = CFArrayGetValueAtIndex(targetSetsMutable, 0);
			CFRetain(targetSet);
			CFArrayRemoveValueAtIndex(targetSetsMutable, 0);
		}
		else {
			targetSet = SCNetworkSetCreate(targetPrefs);
		}
		
		SCNetworkSetSetName(targetSet, setName);
		CFDictionaryAddValue(setMapping, sourceSet, targetSet);
		
		if (CFEqual(sourceSet, currentSourceSet) == TRUE) {
			SCNetworkSetSetCurrent(targetSet);
		}
		CFRelease(targetSet);
	}
	
done:
	if (sourceSets != NULL) {
		CFRelease(sourceSets);
	}
	if (targetSets != NULL) {
		CFRelease(targetSets);
	}
	if (targetSetsMutable != NULL) {
		CFRelease(targetSetsMutable);
	}
	if (currentSourceSet != NULL) {
		CFRelease(currentSourceSet);
	}
	return setMapping;
}

// This function finds the mapping between source and target preferences (SCNetworkServicesRef -> SCNetworkServicesRef)
// If there is no mapping found between source and target preferences, then the CFBooleanRef value indicating no value is found is stored (SCNetworkServicesRef -> kCFBooleanFalse)
static CFDictionaryRef
_SCNetworkMigrationCreateServiceMappingUsingBSDMapping(SCPreferencesRef sourcePrefs,
						       SCPreferencesRef targetPrefs,
						       CFDictionaryRef bsdNameMapping)
{
	CFStringRef bsdNameMapTarget = NULL;
	CFMutableDictionaryRef serviceMapping = NULL;                               // Mapping of services between source and target configurations
	CFStringRef sourceBSDName = NULL;
	CFIndex sourceCount = 0;
	SCNetworkInterfaceRef sourceInterface = NULL;
	CFStringRef sourceInterfaceSubType = NULL;		// Check interface type and subtype to be able to transfer VPN
	CFStringRef sourceInterfaceType = NULL;
	CFArrayRef sourceSCNetworkServices = NULL;
	CFMutableArrayRef sourceSCNetworkServicesMutable = NULL;                    // Source SCNetworkServiceRef mutable array
	SCNetworkServiceRef sourceService = NULL;
	CFStringRef targetBSDName = NULL;
	CFIndex targetCount = 0;                                   // Count of Source and Target Services
	SCNetworkInterfaceRef targetInterface = NULL;
	CFStringRef targetInterfaceSubType = NULL;		// services during migration
	CFStringRef targetInterfaceType = NULL;
	CFArrayRef targetSCNetworkServices = NULL;
	CFMutableArrayRef targetSCNetworkServicesMutable = NULL;                    // Target SCNetworkServiceRef mutable array
	SCNetworkServiceRef targetService = NULL;

	// We need BSD Mapping to successfully create service mapping
	if (bsdNameMapping == NULL) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationCreateServiceMappingUsingBSDMapping: BSD Name Mapping is NULL"));
		goto done;
	}
	sourceSCNetworkServices = SCNetworkServiceCopyAll(sourcePrefs);
	if (isA_CFArray(sourceSCNetworkServices) == NULL) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationCreateServiceMappingUsingBSDMapping: sourceSCNetworkServices is NULL or not of the correct CFType"));
		goto done;
	}
	targetSCNetworkServices = SCNetworkServiceCopyAll(targetPrefs);
	if (isA_CFArray(targetSCNetworkServices) == NULL) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationCreateServiceMappingUsingBSDMapping: targetSCNetworkServices is NULL or not of the correct CFType"));
		goto done;
	}

	sourceCount = CFArrayGetCount(sourceSCNetworkServices);

	sourceSCNetworkServicesMutable = CFArrayCreateMutableCopy(NULL, 0, sourceSCNetworkServices);
	targetSCNetworkServicesMutable = CFArrayCreateMutableCopy(NULL, 0, targetSCNetworkServices);

	serviceMapping = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);

	for (CFIndex idx = 0;  idx < sourceCount; idx++) {
		sourceBSDName = NULL;
		sourceService = NULL;
		sourceInterface = NULL;
		sourceInterfaceType = NULL;
		sourceInterfaceSubType = NULL;
		bsdNameMapTarget = NULL;

		targetCount = CFArrayGetCount(targetSCNetworkServicesMutable);
		sourceService = (SCNetworkServiceRef) CFArrayGetValueAtIndex(sourceSCNetworkServicesMutable, idx);

		sourceInterface = SCNetworkServiceGetInterface(sourceService);

		if (sourceInterface == NULL) {
			SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationCreateServiceMappingUsingBSDMapping: sourceInterface is NULL or not of the correct type"));
			continue;
		}

		sourceInterfaceType = __SCNetworkInterfaceGetEntityType(sourceInterface);
		if ((isA_CFString(sourceInterfaceType) != NULL) &&
		    ((CFEqual(sourceInterfaceType, kSCValNetInterfaceTypeVPN) == TRUE) ||
		     (CFEqual(sourceInterfaceType, kSCValNetInterfaceTypePPP) == TRUE))) {
			    sourceInterfaceSubType = __SCNetworkInterfaceGetEntitySubType(sourceInterface);
			    if (isA_CFString(sourceInterfaceSubType) == NULL) {
				    SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationCreateServiceMappingUsingBSDMapping: sourceInterfaceSubType is NULL or not of the correct type"));
				    continue;
			    }
		}
		else if (((isA_CFString(sourceInterfaceType) != NULL) &&
                         (CFEqual(sourceInterfaceType, kSCValNetInterfaceTypeIPSec) == FALSE) &&
			  (CFEqual(sourceInterfaceType, kSCValNetInterfaceType6to4) == FALSE) &&
			  (CFEqual(sourceInterfaceType, kSCValNetInterfaceTypeLoopback) == FALSE)) ||
			 (isA_CFString(sourceInterfaceType) == NULL)) {
			sourceBSDName = SCNetworkInterfaceGetBSDName(sourceInterface);
			if ((isA_CFString(sourceBSDName) == NULL) ||
			    (CFDictionaryContainsKey(bsdNameMapping, sourceBSDName)) == FALSE) {
				SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationCreateServiceMappingUsingBSDMapping: bsdNameMapping doesn't contain sourceBSDName: %@"), (sourceBSDName == NULL) ? CFSTR("NULL") : sourceBSDName);
				continue;
			}

			bsdNameMapTarget = CFDictionaryGetValue(bsdNameMapping, sourceBSDName);
			if (isA_CFString(bsdNameMapTarget) == NULL) {
				SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationCreateServiceMappingUsingBSDMapping: bsdNameMapTarget is NULL or not of the correct CFType"));
				continue;
			}
		}
		// Find the bsd name in target service
		for (CFIndex idx2 = 0; idx2 < targetCount; idx2++) {
			targetService = NULL;
			targetInterface = NULL;
			targetBSDName = NULL;
			targetInterfaceType = NULL;
			targetInterfaceSubType = NULL;

			targetService = (SCNetworkServiceRef) CFArrayGetValueAtIndex(targetSCNetworkServicesMutable, idx2);

			targetInterface = SCNetworkServiceGetInterface(targetService);
			if (targetInterface == NULL) {
				SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationCreateServiceMappingUsingBSDMapping: targetInterface is NULL or not of the correct type"));
				continue;
			}
                        SCLog(_sc_debug, LOG_NOTICE, CFSTR("targetInterface: %@"), targetInterface);
			if (sourceBSDName != NULL) {
				targetBSDName = SCNetworkInterfaceGetBSDName(targetInterface);
				if (isA_CFString(targetBSDName) == NULL) {
					SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationCreateServiceMappingUsingBSDMapping: targetBSDName is NULL or not of the correct type"));
					continue;
				}

				if (CFEqual(targetBSDName, bsdNameMapTarget) == TRUE) {
					SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationCreateServiceMappingUsingBSDMapping: Removing target BSD Name: %@"), targetBSDName);
					CFDictionaryAddValue(serviceMapping, sourceService, targetService);
					CFArrayRemoveValueAtIndex(targetSCNetworkServicesMutable, idx2);
					break;
				}
			}
			else {
				// Source Interface Type should be VPN
				targetInterfaceType = __SCNetworkInterfaceGetEntityType(targetInterface);
				if ((isA_CFString(targetInterfaceType) == NULL) ||
				    ((CFEqual(targetInterfaceType, kSCValNetInterfaceTypeVPN) == FALSE) &&
				     (CFEqual(targetInterfaceType, kSCValNetInterfaceTypePPP) == FALSE))) {
					    SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationCreateServiceMappingUsingBSDMapping: targetInterfaceType is NULL or not of the correct type : %@"), (targetInterfaceType != NULL) ? targetInterfaceType : CFSTR("NULL"));
					    continue;
				    }
				targetInterfaceSubType = __SCNetworkInterfaceGetEntitySubType(targetInterface);
				if (isA_CFString(targetInterfaceSubType) == NULL) {
					SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationCreateServiceMappingUsingBSDMapping: targetInterfaceSubType is NULL or not of the correct type: %@"), (targetInterfaceSubType != NULL) ? targetInterfaceSubType : CFSTR("NULL"));
					continue;
				}

				// Check if the target interface type and the target interface sub type match
				if ((CFEqual(targetInterfaceType, sourceInterfaceType) == TRUE) &&
				    (CFEqual(targetInterfaceSubType, sourceInterfaceSubType) == TRUE)) {
					SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationCreateServiceMappingUsingBSDMapping: Removing target BSD Name: %@ for VPN"), targetBSDName);
					CFDictionaryAddValue(serviceMapping, sourceService, targetService);
					CFArrayRemoveValueAtIndex(targetSCNetworkServicesMutable, idx2);
					break;
				}
			}
		}
		// Check if sourceService has found a mapping or not, if not the create a NULL mapping to indicate
		// the this service needs to be added and not replaced
		if (CFDictionaryContainsKey(serviceMapping, sourceService) == FALSE) {
			SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationCreateServiceMappingUsingBSDMapping: Service needs to be added: %@"), sourceService);
			CFDictionaryAddValue(serviceMapping, sourceService, kCFBooleanFalse);
		}
	}
done:
	if (sourceSCNetworkServices != NULL) {
		CFRelease(sourceSCNetworkServices);
	}
	if (targetSCNetworkServices != NULL) {
		CFRelease(targetSCNetworkServices);
	}
	if (sourceSCNetworkServicesMutable != NULL) {
		CFRelease(sourceSCNetworkServicesMutable);
	}
	if (targetSCNetworkServicesMutable != NULL) {
		CFRelease(targetSCNetworkServicesMutable);
	}
	return serviceMapping;
}

typedef struct {
	SCPreferencesRef targetPrefs;
	CFDictionaryRef bsdMapping;
	CFDictionaryRef setMapping;
	CFDictionaryRef serviceSetMapping;
} ServiceMigrationContext;

// value can be:
//	SCNetworkServiceRef: if target service needs replacement
//	CFBooleanRef: if target service is not present
static void
ServiceMigrationAddOrReplace(const void *key, const void *value, void *context)
{
	CFDictionaryRef bsdMapping = NULL;
	ServiceMigrationContext *ctx = (ServiceMigrationContext*)context;
	CFDictionaryRef setMapping;
	CFDictionaryRef sourceServiceSetMapping;
	SCNetworkServiceRef sourceService = (SCNetworkServiceRef)key;
	SCPreferencesRef targetPrefs = NULL;
	SCNetworkServiceRef targetService = (SCNetworkServiceRef)value;

	targetPrefs = ctx->targetPrefs;
	bsdMapping = ctx->bsdMapping;
	setMapping = ctx->setMapping;
	sourceServiceSetMapping = ctx->serviceSetMapping;
	
	if (isA_SCNetworkService(targetService) != NULL) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("ServiceMigrationAddOrReplace: Removing target service: %@"), targetService);
		SCNetworkServiceRemove(targetService);
	}
	SCLog(_sc_debug, LOG_NOTICE, CFSTR("ServiceMigrationAddOrReplace: Adding service with %@"), sourceService);
	if (__SCNetworkServiceMigrateNew(targetPrefs, sourceService, bsdMapping, setMapping, sourceServiceSetMapping) ==  FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("Could not Add Service: %@"), sourceService);
	}
}

static Boolean
_SCNetworkMigrationDoServiceMigration(SCPreferencesRef sourcePrefs, SCPreferencesRef targetPrefs,
				      CFDictionaryRef serviceMapping, CFDictionaryRef bsdMapping,
				      CFDictionaryRef setMapping, CFDictionaryRef serviceSetMapping)
{
	ServiceMigrationContext context;
	Boolean success = FALSE;

	if ((sourcePrefs == NULL) ||
	    (targetPrefs == NULL) ||
	    (isA_CFDictionary(serviceMapping) == NULL) ||
	    (isA_CFDictionary(bsdMapping) == NULL)) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationDoServiceMigration: targetPrefs or serviceMapping or bsdMapping is NULL"));
		goto done;
	}
	context.targetPrefs = targetPrefs;
	context.bsdMapping = bsdMapping;
	context.setMapping = setMapping;
	context.serviceSetMapping = serviceSetMapping;
	
	CFDictionaryApplyFunction(serviceMapping, ServiceMigrationAddOrReplace, &context);

	success = TRUE;
done:
	return success;
}

static Boolean
_SCNetworkMigrationDoSystemMigration(SCPreferencesRef sourcePrefs, SCPreferencesRef targetPrefs)
{
	CFStringEncoding nameEncoding;
	CFStringRef computerName;
	CFStringRef hostname;
	CFStringRef localHostname;
	CFDictionaryRef btmm = NULL;
	CFDictionaryRef btmmDSID = NULL;
	CFStringRef btmmDSIDPath;
	CFStringRef btmmPath;
	
	
	if ((sourcePrefs == NULL) ||
	    (targetPrefs == NULL)) {
		return FALSE;
	}

	hostname = SCPreferencesGetHostName(sourcePrefs);
	if (hostname != NULL) {
		SCPreferencesSetHostName(targetPrefs, hostname);
	}

	localHostname = _SCPreferencesCopyLocalHostName(sourcePrefs);
	if (localHostname != NULL) {
		SCPreferencesSetLocalHostName(targetPrefs, localHostname);
		CFRelease(localHostname);
	}

	computerName = _SCPreferencesCopyComputerName(sourcePrefs, &nameEncoding);

	if (computerName != NULL) {
		SCPreferencesSetComputerName(targetPrefs, computerName, nameEncoding);
		CFRelease(computerName);
	}
	
	btmmPath = CFStringCreateWithFormat(NULL, NULL,
					    CFSTR("/%@/%@/%@"),
					    kSCPrefSystem,
					    kSCCompNetwork,
					    BACK_TO_MY_MAC);
	btmm = SCPreferencesPathGetValue(sourcePrefs, btmmPath);
	
	if (btmm != NULL) {
		SCPreferencesPathSetValue(targetPrefs, btmmPath, btmm);
	}
	CFRelease(btmmPath);
	
	btmmDSIDPath = CFStringCreateWithFormat(NULL, NULL,
						CFSTR("/%@/%@/%@"),
						kSCPrefSystem,
						kSCCompNetwork,
						BACK_TO_MY_MAC_DSIDS);
	
	btmmDSID = SCPreferencesPathGetValue(sourcePrefs, btmmDSIDPath);
	if (btmmDSID != NULL) {
		SCPreferencesPathSetValue(targetPrefs, btmmDSIDPath, btmmDSID);
	}
	CFRelease(btmmDSIDPath);

	return TRUE;
}
#if	!TARGET_OS_IPHONE

typedef struct {
	CFMutableArrayRef interfaceList;
	SCPreferencesRef ni_prefs;
	CFDictionaryRef bsdMapping;
} SCVirtualInterfaceMemberListContext;

typedef struct {
	SCPreferencesRef prefs;
	SCPreferencesRef ni_prefs;
	CFDictionaryRef bsdMapping;
	CFDictionaryRef virtualBSDMapping;
	CFDictionaryRef mappingBSDNameToService;
	CFDictionaryRef setMapping;
	CFDictionaryRef serviceSetMapping;
} SCVirtualInterfaceContext;

static void
add_virtual_interface(const void *value, void *context)
{
	SCVirtualInterfaceMemberListContext *ctx = (SCVirtualInterfaceMemberListContext*)context;
	CFMutableArrayRef interfaceList = ctx->interfaceList;
	CFDictionaryRef bsdMapping = ctx->bsdMapping;
	CFStringRef oldInterfaceBSDName = (CFStringRef)value;
	SCNetworkInterfaceRef newInterface;
	CFStringRef newInterfaceBSDName;
	
	SCLog(_sc_debug, LOG_NOTICE, CFSTR("old interface BSD name is %@"), oldInterfaceBSDName);
	newInterfaceBSDName = CFDictionaryGetValue(bsdMapping, oldInterfaceBSDName);
	if (newInterfaceBSDName == NULL) {
		return;
	}
	
	SCLog(_sc_debug, LOG_NOTICE, CFSTR("new interface BSD name is %@"), newInterfaceBSDName);
	newInterface = __SCNetworkInterfaceCreateWithNIPreferencesUsingBSDName(NULL, ctx->ni_prefs, newInterfaceBSDName);
	
	if (newInterface != NULL) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("Adding interface to interfaceList: %@"), newInterface);
		CFArrayAppendValue(interfaceList, newInterface);
		CFRelease(newInterface);
	}
	return;
}

static void
add_target_bridge(const void *key, const void *value, void *context)
{
	CFStringRef bridgeName;
	CFDictionaryRef bridgeOptions;
	SCVirtualInterfaceContext *ctx = (SCVirtualInterfaceContext*)context;
	CFDictionaryRef bridgeBSDNameMapping = ctx->virtualBSDMapping;
	CFDictionaryRef bsdNameToServiceMapping = ctx->mappingBSDNameToService;
	SCVirtualInterfaceMemberListContext memberListContext;
	CFMutableArrayRef newInterfaceList;
	SCBridgeInterfaceRef newBridge;
	SCBridgeInterfaceRef oldBridge = (SCBridgeInterfaceRef)key;
	CFStringRef oldBSDName;
	CFArrayRef oldInterfaceList = (CFArrayRef)value;
	CFArrayRef oldServiceList;
	SCPreferencesRef prefs = ctx->prefs;
	CFDictionaryRef serviceSetMapping = ctx->serviceSetMapping;
	CFDictionaryRef setMapping = ctx->setMapping;
	
	newInterfaceList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
	
	memberListContext.bsdMapping = ctx->bsdMapping;
	memberListContext.interfaceList = newInterfaceList;
	memberListContext.ni_prefs = ctx->ni_prefs;
	
	CFArrayApplyFunction(oldInterfaceList, CFRangeMake(0, CFArrayGetCount(oldInterfaceList)), add_virtual_interface, &memberListContext);
	
	newBridge = SCBridgeInterfaceCreate(prefs);
	
	if (__SCBridgeInterfaceSetMemberInterfaces(newBridge, newInterfaceList) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("add_target_bridge: Adding Member Interfaces failed"));
	}
	CFRelease(newInterfaceList);
	
	bridgeOptions = SCBridgeInterfaceGetOptions(oldBridge);
	if (bridgeOptions != NULL) {
		SCBridgeInterfaceSetOptions(newBridge, bridgeOptions);
	}
	
	bridgeName = SCNetworkInterfaceGetLocalizedDisplayName(oldBridge);
	
	if (bridgeName != NULL) {
		SCBridgeInterfaceSetLocalizedDisplayName(newBridge, bridgeName);
	}
	
	oldBSDName = SCNetworkInterfaceGetBSDName(oldBridge);
	if (oldBSDName == NULL) {
		goto done;
	}
	
	oldServiceList = CFDictionaryGetValue(bsdNameToServiceMapping, oldBSDName);
	if (oldServiceList == NULL) {
		goto done;
	}
	
	for (CFIndex idx = 0; idx < CFArrayGetCount(oldServiceList); idx++) {
		SCNetworkServiceRef oldService = CFArrayGetValueAtIndex(oldServiceList, idx);
		if (__SCNetworkServiceMigrateNew(prefs, oldService, bridgeBSDNameMapping, setMapping, serviceSetMapping) == FALSE) {
			SCLog(_sc_debug, LOG_NOTICE, CFSTR("add_target_bridge: Could not migrate service: %@"), oldService);
		}
	}
done:
	CFRelease(newBridge);
}

static void
_SCNetworkMigrationRemoveBridgeServices(SCPreferencesRef prefs)
{
	CFArrayRef services = SCNetworkServiceCopyAll(prefs);
	
	for (CFIndex idx = 0; idx < CFArrayGetCount(services); idx++) {
		SCNetworkServiceRef service = CFArrayGetValueAtIndex(services, idx);
		SCNetworkInterfaceRef interface = SCNetworkServiceGetInterface(service);
		CFStringRef bsdName = SCNetworkInterfaceGetBSDName(interface);
		
		if ((bsdName != NULL) &&
		SCNetworkInterfaceGetInterfaceType(interface) == kSCNetworkInterfaceTypeBridge) {
			SCLog(TRUE, LOG_NOTICE, CFSTR("_SCNetworkMigrationRemoveBridgeServices: Removing services: %@"), service);
			SCNetworkServiceRemove(service);
		}
	}
	CFRelease(services);
}


static CFDictionaryRef
_SCNetworkMigrationCopyMappingBSDNameToBridgeServices(SCPreferencesRef prefs)
{
	CFArrayRef services = SCNetworkServiceCopyAll(prefs);
	CFMutableDictionaryRef bridgeServices = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
	
	for (CFIndex idx = 0; idx < CFArrayGetCount(services); idx++) {
		SCNetworkServiceRef service = CFArrayGetValueAtIndex(services, idx);
		SCNetworkInterfaceRef interface = SCNetworkServiceGetInterface(service);
		CFStringRef bsdName = SCNetworkInterfaceGetBSDName(interface);
		
		if ((bsdName != NULL) &&
		SCNetworkInterfaceGetInterfaceType(interface) == kSCNetworkInterfaceTypeBridge) {
			CFMutableArrayRef serviceList;
			if (CFDictionaryContainsKey(bridgeServices, bsdName) == FALSE) {
				serviceList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
				CFDictionaryAddValue(bridgeServices, bsdName, serviceList);
				CFRelease(serviceList);
			}
			serviceList = (CFMutableArrayRef)CFDictionaryGetValue(bridgeServices, bsdName);
			CFArrayAppendValue(serviceList, service);
		}
	}
	CFRelease(services);
	return bridgeServices;
}


static Boolean
_SCNetworkMigrationDoBridgeMigration (SCPreferencesRef sourcePrefs,
				      SCPreferencesRef sourceNIPrefs,
				      SCPreferencesRef targetPrefs,
				      SCPreferencesRef targetNIPrefs,
				      CFDictionaryRef bsdMapping,
				      CFDictionaryRef setMapping,
				      CFDictionaryRef serviceSetMapping)
{
	CFArrayRef allSourceBridges;
	CFArrayRef allTargetBridges;
	SCBridgeInterfaceRef bridge;
	CFMutableDictionaryRef bridgeInterfaceMapping = NULL;
	CFMutableDictionaryRef bridgeMapping;
	CFDictionaryRef bsdNameToBridgeServices;
	SCVirtualInterfaceContext context;
	CFIndex count = 0;
	Boolean success = FALSE;
	
	allSourceBridges = SCBridgeInterfaceCopyAll(sourcePrefs);
	allTargetBridges = SCBridgeInterfaceCopyAll(targetPrefs);
	
	bsdNameToBridgeServices = _SCNetworkMigrationCopyMappingBSDNameToBridgeServices(sourcePrefs);
	
	bridgeInterfaceMapping = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
	bridgeMapping = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
	
	// Create Bridge Interface Mapping
	for (CFIndex idx = 0; idx < CFArrayGetCount(allSourceBridges); idx++) {
		bridge = CFArrayGetValueAtIndex(allSourceBridges, idx);
		CFArrayRef bridgeMembers = SCBridgeInterfaceGetMemberInterfaces(bridge);
		CFMutableArrayRef interfaceList;
		
		interfaceList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
		for (CFIndex idx2 = 0; idx2 < CFArrayGetCount(bridgeMembers); idx2++) {
			CFStringRef interfaceName = NULL;
			SCNetworkInterfaceRef interface = NULL;
			
			interface = CFArrayGetValueAtIndex(bridgeMembers, idx2);
			interfaceName = SCNetworkInterfaceGetBSDName(interface);
			
			if (CFDictionaryContainsKey(bsdMapping, interfaceName) == TRUE) {
				CFStringRef bridgeNewName = CFStringCreateWithFormat(NULL, NULL, CFSTR("bridge%ld"), count);
				CFDictionaryAddValue(bridgeMapping, interfaceName, bridgeNewName);
				CFArrayAppendValue(interfaceList, interfaceName);
				CFRelease(bridgeNewName);
				count++;
			}
		}
		if (CFArrayGetCount(interfaceList) > 0) {
			CFDictionaryAddValue(bridgeInterfaceMapping, bridge, interfaceList);
		}
		CFRelease(interfaceList);
	}
	// Remove bridge services from target
	_SCNetworkMigrationRemoveBridgeServices(targetPrefs);
	
	// Remove Target Bridges
	for (CFIndex idx = 0; idx < CFArrayGetCount(allTargetBridges); idx++) {
		bridge = CFArrayGetValueAtIndex(allTargetBridges, idx);
		if (SCBridgeInterfaceRemove(bridge) == FALSE) {
			SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationDoBridgeMigration: Could not remove bridge: %@"), bridge);
			goto done;
		}
	}
	
	context.prefs = targetPrefs;
	context.ni_prefs = targetNIPrefs;
	context.bsdMapping = bsdMapping;
	context.virtualBSDMapping = bridgeMapping;
	context.mappingBSDNameToService = bsdNameToBridgeServices;
	context.setMapping = setMapping;
	context.serviceSetMapping = serviceSetMapping;
	
	// Add Bridge configurations at the target using mapping
	CFDictionaryApplyFunction(bridgeInterfaceMapping, add_target_bridge, &context);
	
	success = TRUE;
done:
	CFRelease(allSourceBridges);
	CFRelease(allTargetBridges);
	CFRelease(bridgeInterfaceMapping);
	CFRelease(bridgeMapping);
	CFRelease(bsdNameToBridgeServices);
	return success;
}


static void
add_target_bond(const void *key, const void *value, void *context)
{
	CFNumberRef bondMode;
	CFStringRef bondName;
	CFDictionaryRef bondOptions;
	SCVirtualInterfaceContext *ctx = (SCVirtualInterfaceContext*)context;
	CFDictionaryRef bondBSDNameMapping = ctx->virtualBSDMapping;
	CFDictionaryRef bsdNameToServiceMapping = ctx->mappingBSDNameToService;
	SCVirtualInterfaceMemberListContext memberListContext;
	CFMutableArrayRef newInterfaceList;
	SCBondInterfaceRef newBond;
	SCBondInterfaceRef oldBond = (SCBondInterfaceRef)key;
	CFStringRef oldBSDName;
	CFArrayRef oldInterfaceList = (CFArrayRef)value;
	CFArrayRef oldServiceList;
	SCPreferencesRef prefs = ctx->prefs;
	CFDictionaryRef serviceSetMapping = ctx->serviceSetMapping;
	CFDictionaryRef setMapping = ctx->setMapping;
	
	newInterfaceList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
	
	memberListContext.bsdMapping = ctx->bsdMapping;
	memberListContext.interfaceList = newInterfaceList;
	memberListContext.ni_prefs = ctx->ni_prefs;
	
	CFArrayApplyFunction(oldInterfaceList, CFRangeMake(0, CFArrayGetCount(oldInterfaceList)), add_virtual_interface, &memberListContext);
	
	newBond = SCBondInterfaceCreate(prefs);
	if (__SCBondInterfaceSetMemberInterfaces(newBond, newInterfaceList) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("add_target_bond: Adding member interface failed."));
	}
	CFRelease(newInterfaceList);
	
	bondOptions = SCBondInterfaceGetOptions(oldBond);
	if (bondOptions != NULL) {
		SCBondInterfaceSetOptions(newBond, bondOptions);
	}
	
	bondName = SCNetworkInterfaceGetLocalizedDisplayName(oldBond);
	if (bondName != NULL) {
		SCBondInterfaceSetLocalizedDisplayName(newBond, bondName);
	}
	
	bondMode = SCBondInterfaceGetMode(oldBond);
	if (bondMode != NULL) {
		SCBondInterfaceSetMode(newBond, bondMode);
	}
	oldBSDName = SCNetworkInterfaceGetBSDName(oldBond);
	if (oldBSDName == NULL) {
		goto done;
	}
	
	oldServiceList = CFDictionaryGetValue(bsdNameToServiceMapping, oldBSDName);
	if (oldServiceList == NULL) {
		goto done;
	}
	
	for (CFIndex idx = 0; idx < CFArrayGetCount(oldServiceList); idx++) {
		SCNetworkServiceRef oldService = CFArrayGetValueAtIndex(oldServiceList, idx);
		if (__SCNetworkServiceMigrateNew(prefs, oldService, bondBSDNameMapping, setMapping, serviceSetMapping) == FALSE) {
			SCLog(_sc_debug, LOG_NOTICE, CFSTR("add_target_bond: Could not migrate service: %@"), oldService);
		}
	}
done:
	CFRelease(newBond);
}

static void
_SCNetworkMigrationRemoveBondServices(SCPreferencesRef prefs)
{
	CFArrayRef services = SCNetworkServiceCopyAll(prefs);
	
	for (CFIndex idx = 0; idx < CFArrayGetCount(services); idx++) {
		SCNetworkServiceRef service = CFArrayGetValueAtIndex(services, idx);
		SCNetworkInterfaceRef interface = SCNetworkServiceGetInterface(service);
		CFStringRef bsdName = SCNetworkInterfaceGetBSDName(interface);
		
		if ((bsdName != NULL) &&
		SCNetworkInterfaceGetInterfaceType(interface) == kSCNetworkInterfaceTypeBond) {
			SCNetworkServiceRemove(service);
		}
	}
	CFRelease(services);
}


static CFDictionaryRef
_SCNetworkMigrationCopyMappingBSDNameToBondServices(SCPreferencesRef prefs)
{
	CFArrayRef services = SCNetworkServiceCopyAll(prefs);
	CFMutableDictionaryRef bondServices = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
	
	for (CFIndex idx = 0; idx < CFArrayGetCount(services); idx++) {
		SCNetworkServiceRef service = CFArrayGetValueAtIndex(services, idx);
		SCNetworkInterfaceRef interface = SCNetworkServiceGetInterface(service);
		CFStringRef bsdName = SCNetworkInterfaceGetBSDName(interface);
		
		if ((bsdName != NULL) &&
		SCNetworkInterfaceGetInterfaceType(interface) == kSCNetworkInterfaceTypeBond) {
			CFMutableArrayRef serviceList;
			if (CFDictionaryContainsKey(bondServices, bsdName) == FALSE) {
				serviceList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
				CFDictionaryAddValue(bondServices, bsdName, serviceList);
				CFRelease(serviceList);
			}
			serviceList = (CFMutableArrayRef)CFDictionaryGetValue(bondServices, bsdName);
			CFArrayAppendValue(serviceList, service);
		}
	}
	CFRelease(services);
	return bondServices;
}


static Boolean
_SCNetworkMigrationDoBondMigration (SCPreferencesRef sourcePrefs,
				    SCPreferencesRef sourceNIPrefs,
				    SCPreferencesRef targetPrefs,
				    SCPreferencesRef targetNIPrefs,
				    CFDictionaryRef bsdMapping,
				    CFDictionaryRef setMapping,
				    CFDictionaryRef serviceSetMapping)
{
	CFArrayRef allSourceBonds;
	CFArrayRef allTargetBonds;
	SCBondInterfaceRef bond;
	CFMutableDictionaryRef bondInterfaceMapping = NULL;
	CFMutableDictionaryRef bondMapping;
	CFDictionaryRef bsdNameToBondServices;
	SCVirtualInterfaceContext context;
	CFIndex count = 0;
	Boolean success = FALSE;
	
	allSourceBonds = SCBondInterfaceCopyAll(sourcePrefs);
	allTargetBonds = SCBondInterfaceCopyAll(targetPrefs);
	
	bsdNameToBondServices = _SCNetworkMigrationCopyMappingBSDNameToBondServices(sourcePrefs);
	
	bondInterfaceMapping = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
	bondMapping = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
	// Create Bond Interface mapping
	for (CFIndex idx = 0; idx < CFArrayGetCount(allSourceBonds); idx++) {
		bond = CFArrayGetValueAtIndex(allSourceBonds, idx);
		CFArrayRef bondMembers = SCBondInterfaceGetMemberInterfaces(bond);
		CFMutableArrayRef interfaceList;
		
		interfaceList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
		for (CFIndex idx2 = 0; idx2 < CFArrayGetCount(bondMembers); idx2++) {
			CFStringRef interfaceName;
			SCNetworkInterfaceRef interface;
			
			interface = CFArrayGetValueAtIndex(bondMembers, idx2);
			interfaceName = SCNetworkInterfaceGetBSDName(interface);
			
			if (CFDictionaryContainsKey(bsdMapping, interfaceName) == TRUE) {
				CFStringRef bondNewName = CFStringCreateWithFormat(NULL, NULL, CFSTR("bond%ld"), count);
				CFDictionaryAddValue(bondMapping, interfaceName, bondNewName);
				CFArrayAppendValue(interfaceList, interfaceName);
				CFRelease(bondNewName);
				count++;
			}
		}
		if (CFArrayGetCount(interfaceList) > 0) {
			CFDictionaryAddValue(bondInterfaceMapping, bond, interfaceList);
		}
		CFRelease(interfaceList);
	}
	// Remove bond services from target
	_SCNetworkMigrationRemoveBondServices(targetPrefs);
	
	// Remove Target Bonds
	for (CFIndex idx = 0; idx < CFArrayGetCount(allTargetBonds); idx++) {
		bond = CFArrayGetValueAtIndex(allTargetBonds, idx);
		if (SCBondInterfaceRemove(bond) == FALSE) {
			SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationDoBondMigration: Could not remove bond: %@"), bond);
			goto done;
		}
	}
	
	context.prefs = targetPrefs;
	context.ni_prefs = targetNIPrefs;
	context.bsdMapping = bsdMapping;
	context.virtualBSDMapping = bondMapping;
	context.mappingBSDNameToService = bsdNameToBondServices;
	context.setMapping = setMapping;
	context.serviceSetMapping = serviceSetMapping;
	
	// Add Bond configurations at the target using mapping
	CFDictionaryApplyFunction(bondInterfaceMapping, add_target_bond, &context);
	
	success = TRUE;
done:
	CFRelease(allSourceBonds);
	CFRelease(allTargetBonds);
	CFRelease(bondInterfaceMapping);
	CFRelease(bondMapping);
	CFRelease(bsdNameToBondServices);
	return success;
}

static void
add_target_vlan(const void *value, void *context)
{
	CFDictionaryRef bsdMapping;
	SCVirtualInterfaceContext *ctx = (SCVirtualInterfaceContext*)context;
	CFDictionaryRef bsdNameToServiceMapping = ctx->mappingBSDNameToService;
	SCPreferencesRef prefs = ctx->prefs;
	SCVLANInterfaceRef newVLAN = NULL;
	SCNetworkInterfaceRef newPhysicalInterface = NULL;
	CFStringRef newPhysicalInterfaceName;
	SCVLANInterfaceRef oldVLAN = (SCVLANInterfaceRef)value;
	CFStringRef oldBSDName;
	SCNetworkInterfaceRef oldPhysicalInterface;
	CFStringRef oldPhysicalInterfaceName;
	SCNetworkServiceRef oldService;
	CFArrayRef oldServiceList;
	CFDictionaryRef serviceSetMapping = ctx->serviceSetMapping;
	CFDictionaryRef setMapping = ctx->setMapping;
	CFDictionaryRef vlanBSDMapping = ctx->virtualBSDMapping;
	CFNumberRef vlanTag;
	CFStringRef vlanName;
	CFDictionaryRef vlanOptions;
	
	bsdMapping = ctx->bsdMapping;
	oldPhysicalInterface = SCVLANInterfaceGetPhysicalInterface(oldVLAN);
	
	if (oldPhysicalInterface == NULL) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("add_target_vlan: oldPhysicalInterface is NULL"));
		goto done;
	}
	oldPhysicalInterfaceName = SCNetworkInterfaceGetBSDName(oldPhysicalInterface);
	
	if (oldPhysicalInterfaceName == NULL) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("add_target_vlan: oldPhysicalInterfaceName is NULL"));
		goto done;
	}
	
	newPhysicalInterfaceName = CFDictionaryGetValue(bsdMapping, oldPhysicalInterfaceName);
	if (newPhysicalInterfaceName == NULL) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("add_target_vlan: newPhysicalInterfaceName is NULL"));
		goto done;
	}
	newPhysicalInterface = __SCNetworkInterfaceCreateWithNIPreferencesUsingBSDName(NULL, ctx->ni_prefs, newPhysicalInterfaceName);
	if (newPhysicalInterface == NULL) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("add_target_vlan: newPhysicalInterface is NULL"));
		goto done;
	}
	
	vlanTag = SCVLANInterfaceGetTag(oldVLAN);
	if (vlanTag == NULL) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("add_target_vlan: vlanTag is NULL"));
		goto done;
	}
	
	newVLAN = SCVLANInterfaceCreate(prefs, newPhysicalInterface, vlanTag);
	if (newVLAN == NULL) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("add_target_vlan: Could not create newVLAN"));
	}
	
	vlanName = SCNetworkInterfaceGetLocalizedDisplayName(oldVLAN);
	if (vlanName != NULL) {
		SCVLANInterfaceSetLocalizedDisplayName(newVLAN, vlanName);
	}
	
	vlanOptions = SCVLANInterfaceGetOptions(oldVLAN);
	if (vlanOptions != NULL) {
		SCVLANInterfaceSetOptions(newVLAN, vlanOptions);
	}
	oldBSDName = SCNetworkInterfaceGetBSDName(oldVLAN);
	
	if (oldBSDName == NULL) {
		goto done;
	}
	
	oldServiceList = CFDictionaryGetValue(bsdNameToServiceMapping, oldBSDName);
	if (oldServiceList == NULL) {
		goto done;
	}
	
	for (CFIndex idx = 0; idx < CFArrayGetCount(oldServiceList); idx++) {
		oldService = CFArrayGetValueAtIndex(oldServiceList, idx);
		if (__SCNetworkServiceMigrateNew(prefs, oldService, vlanBSDMapping, setMapping, serviceSetMapping) == FALSE) {
			SCLog(_sc_debug, LOG_NOTICE, CFSTR("add_target_vlan: Could not migrate service: %@"), oldService);
		}
	}
	
done:
	if (newPhysicalInterface != NULL) {
		CFRelease(newPhysicalInterface);
	}
	if (newVLAN != NULL) {
		CFRelease(newVLAN);
	}
}

static void
_SCNetworkMigrationRemoveVLANServices(SCPreferencesRef prefs)
{
	CFArrayRef services = SCNetworkServiceCopyAll(prefs);
	
	for (CFIndex idx = 0; idx < CFArrayGetCount(services); idx++) {
		SCNetworkServiceRef service = CFArrayGetValueAtIndex(services, idx);
		SCNetworkInterfaceRef interface = SCNetworkServiceGetInterface(service);
		CFStringRef bsdName = SCNetworkInterfaceGetBSDName(interface);
		
		if ((bsdName != NULL) &&
		    SCNetworkInterfaceGetInterfaceType(interface) == kSCNetworkInterfaceTypeVLAN) {
			SCNetworkServiceRemove(service);
		}
	}
	
	CFRelease(services);
}


static CFDictionaryRef
_SCNetworkMigrationCopyMappingBSDNameToVLANServices(SCPreferencesRef prefs)
{
	CFArrayRef services = SCNetworkServiceCopyAll(prefs);
	CFMutableDictionaryRef vlanServices = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
	
	for (CFIndex idx = 0; idx < CFArrayGetCount(services); idx++) {
		SCNetworkServiceRef service = CFArrayGetValueAtIndex(services, idx);
		SCNetworkInterfaceRef interface = SCNetworkServiceGetInterface(service);
		CFStringRef bsdName = SCNetworkInterfaceGetBSDName(interface);
		
		if ((bsdName != NULL) &&
		    SCNetworkInterfaceGetInterfaceType(interface) == kSCNetworkInterfaceTypeVLAN) {
			CFMutableArrayRef serviceList;
			if (CFDictionaryContainsKey(vlanServices, bsdName) == FALSE) {
				serviceList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
				CFDictionaryAddValue(vlanServices, bsdName, serviceList);
				CFRelease(serviceList);
			}
			serviceList = (CFMutableArrayRef)CFDictionaryGetValue(vlanServices, bsdName);
			CFArrayAppendValue(serviceList, service);
		}
	}
	CFRelease(services);
	return vlanServices;
}

static Boolean
_SCNetworkMigrationDoVLANMigration (SCPreferencesRef sourcePrefs,
				    SCPreferencesRef sourceNIPrefs,
				    SCPreferencesRef targetPrefs,
				    SCPreferencesRef targetNIPrefs,
				    CFDictionaryRef bsdMapping,
				    CFDictionaryRef setMapping,
				    CFDictionaryRef serviceSetMapping)
{
	CFArrayRef allSourceVLAN;
	CFArrayRef allTargetVLAN;
	SCVirtualInterfaceContext context;
	CFIndex count = 0;
	Boolean success = FALSE;
	SCVLANInterfaceRef vlan;
	CFMutableArrayRef vlanList;
	CFMutableDictionaryRef vlanMapping;
	CFDictionaryRef bsdNameToVLANServices;
	
	allSourceVLAN = SCVLANInterfaceCopyAll(sourcePrefs);
	allTargetVLAN = SCVLANInterfaceCopyAll(targetPrefs);
	
	bsdNameToVLANServices = _SCNetworkMigrationCopyMappingBSDNameToVLANServices(sourcePrefs);
	
	vlanList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
	vlanMapping = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
	
	for (CFIndex idx = 0; idx < CFArrayGetCount(allSourceVLAN); idx++) {
		vlan = CFArrayGetValueAtIndex(allSourceVLAN, idx);
		CFStringRef vlanBSDName = SCNetworkInterfaceGetBSDName(vlan);
		SCNetworkInterfaceRef physicalInterface = SCVLANInterfaceGetPhysicalInterface(vlan);
		CFStringRef physicalInterfaceName;
		
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationDoVLANMigration: physical interface is %@"), physicalInterface);
		
		physicalInterfaceName = SCNetworkInterfaceGetBSDName(physicalInterface);
                SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationDoVLANMigration: Physical Interface name is %@"), physicalInterfaceName);
                
		// Add VLAN to be migrated if the mapping between interfaces exists
		if (CFDictionaryContainsKey(bsdMapping, physicalInterfaceName) == TRUE) {
			CFStringRef vlanNewName = CFStringCreateWithFormat(NULL, NULL, CFSTR("vlan%ld"), count);
			CFDictionaryAddValue(vlanMapping, vlanBSDName, vlanNewName);
			CFArrayAppendValue(vlanList, vlan);
			CFRelease(vlanNewName);
			count++;
		}
	}
	// Remove vlan services from target
	_SCNetworkMigrationRemoveVLANServices(targetPrefs);
	
	// Remove Target VLANs
	for (CFIndex idx = 0; idx < CFArrayGetCount(allTargetVLAN); idx++) {
		vlan = CFArrayGetValueAtIndex(allTargetVLAN, idx);
		if (SCVLANInterfaceRemove(vlan) == FALSE) {
			SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationDoVLANMigration: Could not remove VLAN: %@"), vlan);
			goto done;
		}
	}
	
	context.prefs = targetPrefs;
	context.ni_prefs = targetNIPrefs;
	context.bsdMapping = bsdMapping;
	context.virtualBSDMapping = vlanMapping;
	context.mappingBSDNameToService = bsdNameToVLANServices;
	context.setMapping = setMapping;
	context.serviceSetMapping = serviceSetMapping;
	
	// Add VLAN configurations at the target using vlanList
	CFArrayApplyFunction(vlanList, CFRangeMake(0, CFArrayGetCount(vlanList)), add_target_vlan, &context);
	
	success = TRUE;
done:
	CFRelease(allSourceVLAN);
	CFRelease(allTargetVLAN);
	CFRelease(vlanList);
	CFRelease(vlanMapping);
	CFRelease(bsdNameToVLANServices);
	return success;
}

static Boolean
_SCNetworkMigrationDoVirtualNetworkInterfaceMigration(SCPreferencesRef sourcePrefs,
						      SCPreferencesRef sourceNIPrefs,
						      SCPreferencesRef targetPrefs,
						      SCPreferencesRef targetNIPrefs,
						      CFDictionaryRef bsdMapping,
						      CFDictionaryRef setMapping,
						      CFDictionaryRef serviceSetMapping)
{
	// Handle Bridges
	if (_SCNetworkMigrationDoBridgeMigration(sourcePrefs, sourceNIPrefs,
						 targetPrefs, targetNIPrefs,
						 bsdMapping, setMapping, serviceSetMapping) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationDoVirtualNetworkInterfaceMigration: Bridge migration failed"));
	}
	
	// Handle Bonds
	if (_SCNetworkMigrationDoBondMigration(sourcePrefs, sourceNIPrefs,
					       targetPrefs, targetNIPrefs,
					       bsdMapping, setMapping, serviceSetMapping) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationDoVirtualNetworkInterfaceMigration: Bond migration failed"));
	}
	
	// Handle VLANs
	if (_SCNetworkMigrationDoVLANMigration(sourcePrefs, sourceNIPrefs,
					       targetPrefs, targetNIPrefs,
					       bsdMapping, setMapping, serviceSetMapping) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationDoVirtualNetworkInterfaceMigration: VLAN migration failed"));
	}
	return TRUE;
}
#endif

typedef struct {
	SCPreferencesRef prefs;
	CFArrayRef serviceOrder;
	CFMutableArrayRef serviceListMutable;
	Boolean* success;
} migrated_service_context;

static void
create_migrated_order(const void *value, void *context)
{
	migrated_service_context *ctx = (migrated_service_context*)context;
	CFMutableArrayRef migratedServiceOrder = ctx->serviceListMutable;
	CFArrayRef targetServiceOrder = ctx->serviceOrder;
	CFStringRef migratedServiceID = (CFStringRef)value;
	Boolean *success = ctx->success;
	
	if (*success == FALSE) {
		return;
	}
	// Preserving the service order in the source configuration for the services
	// which were migrated into the target configuration
	for (CFIndex idx = 0; idx < CFArrayGetCount(targetServiceOrder); idx++) {
		CFStringRef targetServiceID = CFArrayGetValueAtIndex(targetServiceOrder, idx);
		if (CFEqual(migratedServiceID, targetServiceID) == TRUE) {
			CFArrayAppendValue(migratedServiceOrder, migratedServiceID);
			return;
		}
	}
}

static void
create_non_migrated_service_list(const void *value, void *context)
{
	migrated_service_context *ctx = (migrated_service_context*)context;
	CFArrayRef migratedServiceOrder = ctx->serviceOrder;
	CFMutableArrayRef nonMigratedService = ctx->serviceListMutable;
	SCPreferencesRef prefs = ctx->prefs;
	SCNetworkServiceRef service;
	Boolean *success = ctx->success;
	CFStringRef targetServiceID = (CFStringRef)value;
	
	if (*success == FALSE) {
		return;
	}
	// Adding all services not present in migratedServiceOrder into nonMigrated service
	for (CFIndex idx = 0; idx < CFArrayGetCount(migratedServiceOrder); idx++) {
		CFStringRef migratedServiceID = CFArrayGetValueAtIndex(migratedServiceOrder, idx);
		
		if (CFEqual(targetServiceID, migratedServiceID) == TRUE) {
			return;
		}
	}
	service = SCNetworkServiceCopy(prefs, targetServiceID);
	if (service == NULL) {
		*success = FALSE;
		return;
	}
	
	CFArrayAppendValue(nonMigratedService, service);
	CFRelease(service);
}

static void
preserve_service_order(const void *key, const void *value, void *context)
{
	migrated_service_context migrated_context;
	CFMutableArrayRef migratedServiceOrder;
	migrated_service_context non_migrated_context;
	CFMutableArrayRef nonMigratedServices;
	SCNetworkSetRef sourceSet = (SCNetworkSetRef)key;
	CFArrayRef sourceServiceOrder = NULL;
	Boolean *success = (Boolean*)context;
	SCNetworkSetRef targetSet = (SCNetworkSetRef)value;
	SCNetworkSetPrivateRef targetPrivate = (SCNetworkSetPrivateRef)targetSet;
	CFArrayRef targetServiceOrder = NULL;
	
	if (*success == FALSE) {
		return;
	}
	migratedServiceOrder = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
	nonMigratedServices = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
	
	sourceServiceOrder = SCNetworkSetGetServiceOrder(sourceSet);
	if (sourceServiceOrder == NULL) {
		goto done;
	}
	targetServiceOrder = SCNetworkSetGetServiceOrder(targetSet);
	if (targetServiceOrder == NULL) {
		goto done;
	}
	
	migrated_context.prefs = NULL;
	migrated_context.serviceOrder = targetServiceOrder;
	migrated_context.serviceListMutable = migratedServiceOrder;
	migrated_context.success = success;
	
	// Creating a list of service IDs which were migrated in the target set
	// while maintaining the service order or the source set
	CFArrayApplyFunction(sourceServiceOrder, CFRangeMake(0, CFArrayGetCount(sourceServiceOrder)), create_migrated_order, &migrated_context);
	
	if (success == FALSE) {
		goto done;
	}
	
	non_migrated_context.prefs = targetPrivate->prefs;
	non_migrated_context.serviceOrder = migratedServiceOrder;
	non_migrated_context.serviceListMutable = nonMigratedServices;
	non_migrated_context.success = success;
	
	// Creating a list of all the services which were not migrated from the source set to the
	// target set
	CFArrayApplyFunction(targetServiceOrder, CFRangeMake(0, CFArrayGetCount(targetServiceOrder)), create_non_migrated_service_list, &non_migrated_context);
	
	// Remove non migrated service
	for (CFIndex idx = 0; idx < CFArrayGetCount(nonMigratedServices); idx++) {
		SCNetworkServiceRef service = CFArrayGetValueAtIndex(nonMigratedServices, idx);
		SCNetworkSetRemoveService(targetSet, service);
	}
	// Set migrated service order
	SCNetworkSetSetServiceOrder(targetSet, migratedServiceOrder);
	
	// Add non migrated services
	for (CFIndex idx = 0; idx < CFArrayGetCount(nonMigratedServices); idx++) {
		SCNetworkServiceRef service = CFArrayGetValueAtIndex(nonMigratedServices, idx);
		SCNetworkSetAddService(targetSet, service);
	}
	
done:
	CFRelease(migratedServiceOrder);
	CFRelease(nonMigratedServices);
	return;
	
}

static Boolean
_SCNetworkMigrationDoServiceOrderMigration(SCPreferencesRef sourcePrefs,
					   SCPreferencesRef targetPrefs,
					   CFDictionaryRef setMapping)
{
	Boolean success = TRUE;
	
	if (isA_CFDictionary(setMapping) == NULL) {
		success = FALSE;
		goto done;
	}
	
	CFDictionaryApplyFunction(setMapping, preserve_service_order, &success);
done:
	return success;
}


// This is a function that looks at source and target network configuration
// and determines what network configurations can be transferred from source to
// target
static Boolean
_SCNetworkConfigurationMigrateConfiguration(CFURLRef sourceDir, CFURLRef targetDir)
{
	CFDictionaryRef bsdNameMapping = NULL;              // Mapping between BSD name and SCNetworkInterfaceRef to help with mapping services
	CFMutableDictionaryRef builtinMapping = NULL;       // Mapping between builtin interfaces between source and target configurations: (SCNetworkInterfaceRef -> SCNetworkInterfaceRef)
	CFMutableDictionaryRef externalMapping = NULL;      // Mapping between external interfaces between source and target configurations: (SCNetworkInterfaceRef -> SCNetworkInterfaceRef)
	Boolean migrationSuccess = FALSE;
	CFArrayRef newTargetNetworkInterfaceEntity = NULL;  // Array of Interface Entity which used to create new target interfaces created during migration
	CFDictionaryRef serviceMapping = NULL;              // Mapping between services of source to target. (SCNetworkServicesRef -> SCNetworkServicesRef)
	CFDictionaryRef setMapping = NULL;
	CFDictionaryRef sourceServiceSetMapping = NULL;
	CFArrayRef sourceConfigurationFiles = NULL;							// Path to the source configuration files which need to be migrated
	CFURLRef sourceNetworkInterfaceFile = NULL;			// Source CFURLRef for preferences.plist and NetworkInterfaces.plist
	char sourceNetworkInterfaceFileStr[PATH_MAX];
	CFStringRef sourceNetworkInterfaceFileString = NULL;	// Source CFStringRef for preferences.plist and NetworkInterfaces.plist
	SCPreferencesRef sourceNetworkInterfacePrefs = NULL;			// Source SCPreferencesRef for preferences.plist and NetworkInterfaces.plist
	CFURLRef sourcePreferencesFile = NULL;
	char sourcePreferencesFileStr[PATH_MAX];
	CFStringRef sourcePreferencesFileString = NULL;
	SCPreferencesRef sourcePrefs = NULL;
	CFArrayRef targetConfigurationFiles = NULL;							// Path to the target configuration files where migration will take place to
	Boolean targetConfigurationFilesPresent;
	CFURLRef targetNetworkInterfaceFile = NULL;			// Target CFURLRef for preferences.plist and NetworkInterfaces.plist
	char targetNetworkInterfaceFileStr[PATH_MAX];
	CFStringRef targetNetworkInterfaceFileString = NULL;	// Target CFStringRef for preferences.plist and NetworkInterfaces.plist
	SCPreferencesRef targetNetworkInterfacePrefs = NULL;			// Target SCPreferencesRef for preferences.plist and NetworkInterfaces.plist
	CFURLRef targetPreferencesFile = NULL;
	char targetPreferencesFileStr[PATH_MAX];
	CFStringRef targetPreferencesFileString = NULL;
	SCPreferencesRef targetPrefs = NULL;
	CFMutableDictionaryRef validityOptions = NULL;

	// Check if configuration files exist in sourceDir
	if (__SCNetworkConfigurationMigrateConfigurationFilesPresent(sourceDir, &sourceConfigurationFiles) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationMigrateConfiguration: sourceDir: (%@) doesn't contain configuration files"), sourceDir);
		goto done;
	}

	sourcePreferencesFile = CFArrayGetValueAtIndex(sourceConfigurationFiles, PREFERENCES_PLIST_INDEX);
	if (CFURLGetFileSystemRepresentation(sourcePreferencesFile, TRUE, (UInt8*)sourcePreferencesFileStr, sizeof(sourcePreferencesFileStr)) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationMigrateConfiguration: Cannot get file system representation for url: %@"), sourcePreferencesFile);
		goto done;
	}

	sourceNetworkInterfaceFile = CFArrayGetValueAtIndex(sourceConfigurationFiles, NETWORK_INTERFACES_PLIST_INDEX);
	if (CFURLGetFileSystemRepresentation(sourceNetworkInterfaceFile, TRUE, (UInt8*)sourceNetworkInterfaceFileStr, sizeof(sourceNetworkInterfaceFileStr)) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationMigrateConfiguration: Cannot get file system representation for url: %@"), sourceNetworkInterfaceFile);
		goto done;
	}

	sourcePreferencesFileString = CFStringCreateWithCString(NULL, sourcePreferencesFileStr, kCFStringEncodingUTF8);
	sourceNetworkInterfaceFileString = CFStringCreateWithCString(NULL, sourceNetworkInterfaceFileStr, kCFStringEncodingUTF8);

	sourcePrefs = SCPreferencesCreate(NULL, PLUGIN_ID, sourcePreferencesFileString);
	sourceNetworkInterfacePrefs = SCPreferencesCreate(NULL, PLUGIN_ID, sourceNetworkInterfaceFileString);
	if ((sourcePrefs == NULL) || (sourceNetworkInterfacePrefs == NULL)) {
		goto done;
	}
	
	if ((targetConfigurationFilesPresent = __SCNetworkConfigurationMigrateConfigurationFilesPresent(targetDir, &targetConfigurationFiles)) == FALSE) {
		if (targetConfigurationFiles == NULL) {
			SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationMigrateConfiguration: targetConfigurationFiles is NULL"));
			goto done;
		}
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationMigrateConfiguration: targetDir: (%@) doesn't contain configuration files ... Need to create default configuration"), targetDir);
	}
	
	targetPreferencesFile = CFArrayGetValueAtIndex(targetConfigurationFiles, PREFERENCES_PLIST_INDEX);
	if (CFURLGetFileSystemRepresentation(targetPreferencesFile, TRUE, (UInt8*)targetPreferencesFileStr, sizeof(targetPreferencesFileStr)) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationMigrateConfiguration: Cannot get file system representation for url: %@"), targetPreferencesFile);
		goto done;
	}
	targetNetworkInterfaceFile = CFArrayGetValueAtIndex(targetConfigurationFiles, NETWORK_INTERFACES_PLIST_INDEX);
	if (CFURLGetFileSystemRepresentation(targetNetworkInterfaceFile, TRUE, (UInt8*)targetNetworkInterfaceFileStr, sizeof(targetNetworkInterfaceFileStr)) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationMigrateConfiguration: Cannot get file system representation for url: %@"), targetNetworkInterfaceFile);
		goto done;
	}

	targetPreferencesFileString = CFStringCreateWithCString(NULL, targetPreferencesFileStr, kCFStringEncodingUTF8);
	targetNetworkInterfaceFileString = CFStringCreateWithCString(NULL, targetNetworkInterfaceFileStr, kCFStringEncodingUTF8);

	if (targetConfigurationFilesPresent == TRUE) {
		targetPrefs = SCPreferencesCreate(NULL, PLUGIN_ID, targetPreferencesFileString);
		targetNetworkInterfacePrefs = SCPreferencesCreate(NULL, PLUGIN_ID, targetNetworkInterfaceFileString);
		if ((targetPrefs == NULL) || (targetNetworkInterfacePrefs == NULL)) {
			goto done;
		}
	}
	else {
		targetPrefs = __SCNetworkCreateDefaultPref(targetPreferencesFileString);
		targetNetworkInterfacePrefs = __SCNetworkCreateDefaultNIPrefs(targetNetworkInterfaceFileString);
		
		if (targetPrefs == NULL ||
		    targetNetworkInterfacePrefs == NULL) {
			SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationMigrateConfiguration: Could not create default configuration."));
			goto done;
		}
	}
	validityOptions = CFDictionaryCreateMutable(NULL, 0,
						    &kCFTypeDictionaryKeyCallBacks,
						    &kCFTypeDictionaryValueCallBacks);
	CFDictionaryAddValue(validityOptions, kSCNetworkConfigurationRepair, kCFBooleanTrue);
	
	SCLog(_sc_debug, LOG_NOTICE, CFSTR("sourcePreferenceFileString: %@\n sourceNetworkInterfaceFileString:%@\n targetPreferencesFileString:%@\ntargetNetworkInterfaceFileString:%@"), sourcePreferencesFileString, sourceNetworkInterfaceFileString,
	      targetPreferencesFileString, targetNetworkInterfaceFileString);

	// Setting Bypass Interface to avoid looking at system interfaces
	__SCPreferencesSetLimitSCNetworkConfiguration(sourcePrefs, TRUE);
	__SCPreferencesSetLimitSCNetworkConfiguration(targetPrefs, TRUE);

	// Create services for builtin interfaces at source if they don't exist
	(void)_SCNetworkConfigurationCreateBuiltinInterfaceServices(sourcePrefs, sourceNetworkInterfacePrefs);
	// Checking validity of the source and destination preferences before continuing
	if (_SCNetworkConfigurationCheckValidityUsingPreferences(sourcePrefs,
								 sourceNetworkInterfacePrefs,
								 validityOptions) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationMigrateConfiguration: Source configuration is not valid"));
		goto skipServiceMigration;
	}
	// Only call this function if configuration files were not created by default
	if (targetConfigurationFilesPresent == TRUE) {
		// Create services for builtin interfaces at target if they don't exist
		(void)_SCNetworkConfigurationCreateBuiltinInterfaceServices(targetPrefs, targetNetworkInterfacePrefs);
		if (_SCNetworkConfigurationCheckValidityUsingPreferences(targetPrefs,
									 targetNetworkInterfacePrefs,
									 validityOptions) == FALSE) {
			SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationMigrateConfiguration: Target configuration is not valid"));
			goto skipServiceMigration;
		}
	}

	builtinMapping = _SCNetworkConfigurationCopyBuiltinMapping(sourceNetworkInterfacePrefs, targetNetworkInterfacePrefs);
	externalMapping = _SCNetworkConfigurationCopyExternalInterfaceMapping(sourceNetworkInterfacePrefs, targetNetworkInterfacePrefs);

	/*
	 TODO:
	 Now builtin and external interface mapping is complete, work needs to be done on updating the preferences.plist and NetworkInterface.plist.

	 Also, work needs to be done to check the validity of the data in preferences in source and target destinations, and after migration
	 */

	newTargetNetworkInterfaceEntity = _SCNetworkMigrationCreateNetworkInterfaceArray(targetNetworkInterfacePrefs, externalMapping);
	if (isA_CFArray(newTargetNetworkInterfaceEntity) == NULL) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationMigrateConfiguration: newTargetNetworkInterfaceEntity is NULL or not of correct type"));
		goto done;
	}
	// Write new interface mapping to NetworkInterfaces.plist
	if (__SCNetworkInterfaceSaveStoredWithPreferences(targetNetworkInterfacePrefs, newTargetNetworkInterfaceEntity) == FALSE)
	{
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationMigrateConfiguration: SCNetworkInterfaceSaveStoreWithPreferences failed to update NetworkInterface.plist"));
		goto done;
	}
	// Create BSD Name Mapping to facilitate mapping of services
	bsdNameMapping = _SCNetworkMigrationCreateBSDNameMapping(builtinMapping, externalMapping);

	if (isA_CFDictionary(bsdNameMapping) == NULL) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationMigrateConfiguration: BSD Name Mapping is NULL"));
		goto done;
	}
	SCLog(_sc_debug, LOG_NOTICE, CFSTR("BSD Name Mapping: %@"), bsdNameMapping);
	serviceMapping = _SCNetworkMigrationCreateServiceMappingUsingBSDMapping(sourcePrefs, targetPrefs, bsdNameMapping);

	if (isA_CFDictionary(serviceMapping) == NULL) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationMigrateConfiguration: Service Mapping is NULL"));
		goto done;
	}
	SCLog(_sc_debug, LOG_NOTICE, CFSTR("Service Mapping: %@"), serviceMapping);

	setMapping = _SCNetworkMigrationCreateSetMapping(sourcePrefs, targetPrefs);
	sourceServiceSetMapping = _SCNetworkMigrationCreateServiceSetMapping(sourcePrefs);
	
	// Perform the migration of services
	if (_SCNetworkMigrationDoServiceMigration(sourcePrefs, targetPrefs,
						  serviceMapping, bsdNameMapping,
						  setMapping, sourceServiceSetMapping) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationMigrateConfiguration: SCNetworkMigrationDoServiceMigration failed to complete successfully"));
		goto done;
	}
	
#if	!TARGET_OS_IPHONE
	// Migrating Virtual Network Interface
	if (_SCNetworkMigrationDoVirtualNetworkInterfaceMigration(sourcePrefs, sourceNetworkInterfacePrefs,
								  targetPrefs, targetNetworkInterfacePrefs,
								  bsdNameMapping, setMapping, sourceServiceSetMapping) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationMigrateConfiguration: _SCNetworkMigrationDoVirtualNetworkInterfaceMigration failed to complete successfully"));
	}
#endif
	// Migrate Service Order
	if (_SCNetworkMigrationDoServiceOrderMigration(sourcePrefs, targetPrefs, setMapping) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationMigrateConfiguration: _SCNetworkMigrationDoServiceOrderMigration failed to complete successfully"));
	}
	
skipServiceMigration:
	// Migrating System Information
	if (_SCNetworkMigrationDoSystemMigration(sourcePrefs, targetPrefs) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationMigrateConfiguration: _SCNetworkMigrationDoSystemMigration failed to complete successfully"));
	}

	if (_SCNetworkConfigurationCheckValidityUsingPreferences(targetPrefs, targetNetworkInterfacePrefs, NULL) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkConfigurationMigrateConfiguration: Migrated configuration is not valid"));
		goto done;
	}
	if (SCPreferencesCommitChanges(targetPrefs) == FALSE) {
		SCLog(TRUE, LOG_ERR, CFSTR("_SCNetworkConfigurationMigrateConfiguration: Error commiting targetPrefs, %s"), SCErrorString(SCError()));
		goto done;
	}

	if (SCPreferencesCommitChanges(targetNetworkInterfacePrefs) == FALSE) {
		SCLog(TRUE, LOG_ERR, CFSTR("_SCNetworkConfigurationMigrateConfiguration: Error commiting targetNetworkInterfacePrefs, %s"), SCErrorString(SCError()));
		goto done;
	}
	migrationSuccess = TRUE;

done:
	if (setMapping != NULL) {
		CFRelease(setMapping);
	}
	if (sourceServiceSetMapping != NULL) {
		CFRelease(sourceServiceSetMapping);
	}
	if (sourceConfigurationFiles != NULL) {
		CFRelease(sourceConfigurationFiles);
	}
	if (targetConfigurationFiles != NULL) {
		CFRelease(targetConfigurationFiles);
	}
	if (sourcePreferencesFileString != NULL) {
		CFRelease(sourcePreferencesFileString);
	}
	if (sourceNetworkInterfaceFileString != NULL) {
		CFRelease(sourceNetworkInterfaceFileString);
	}
	if (targetPreferencesFileString != NULL) {
		CFRelease(targetPreferencesFileString);
	}
	if (targetNetworkInterfaceFileString != NULL) {
		CFRelease(targetNetworkInterfaceFileString);
	}
	if (newTargetNetworkInterfaceEntity != NULL) {
		CFRelease(newTargetNetworkInterfaceEntity);
	}
	if (builtinMapping != NULL) {
		CFRelease(builtinMapping);
	}
	if (externalMapping != NULL) {
		CFRelease(externalMapping);
	}
	if (bsdNameMapping != NULL) {
		CFRelease(bsdNameMapping);
	}
	if (serviceMapping != NULL) {
		CFRelease(serviceMapping);
	}
	if (targetPrefs != NULL) {
		CFRelease(targetPrefs);
	}
	if (sourcePrefs != NULL) {
		CFRelease(sourcePrefs);
	}
	if (sourceNetworkInterfacePrefs != NULL) {
		CFRelease(sourceNetworkInterfacePrefs);
	}
	if (targetNetworkInterfacePrefs != NULL) {
		CFRelease(targetNetworkInterfacePrefs);
	}
	if (validityOptions != NULL) {
		CFRelease(validityOptions);
	}
	return migrationSuccess;
}

#define N_QUICK 64

static Boolean
_SCNetworkMigrationAreServicesIdentical( SCPreferencesRef configPref, SCPreferencesRef expectedConfigPref)
{
	const void * expected_vals_q[N_QUICK];
	const void ** expected_vals = expected_vals_q;
	CFMutableArrayRef expectedServiceArray = NULL;
	CFIndex expectedServiceArrayCount = 0;
	CFDictionaryRef expectedServiceDict = NULL;
	CFIndex expectedServiceDictCount = 0;
	CFDictionaryRef expectedServiceEntity = 0;
	Boolean foundMatch = FALSE;
	CFMutableArrayRef serviceArray = NULL;
	CFIndex serviceArrayCount = 0;
	CFDictionaryRef serviceDict = NULL;
	CFIndex serviceDictCount = 0;
	CFDictionaryRef serviceEntity = NULL;
	Boolean success = FALSE;
	const void * vals_q[N_QUICK];
	const void ** vals = vals_q;

	serviceDict = SCPreferencesGetValue(configPref, kSCPrefNetworkServices);
	if (isA_CFDictionary(serviceDict) == NULL) {
		goto done;
	}
	serviceDictCount = CFDictionaryGetCount(serviceDict);

	expectedServiceDict = SCPreferencesGetValue(expectedConfigPref, kSCPrefNetworkServices);
	if (isA_CFDictionary(expectedServiceDict) == NULL) {
		goto done;
	}
	expectedServiceDictCount = CFDictionaryGetCount(expectedServiceDict);

	if (serviceDictCount != expectedServiceDictCount) {
		goto done;
	}

	if (serviceDictCount > (sizeof(vals_q) / sizeof(CFTypeRef))) {
		vals = CFAllocatorAllocate(NULL, serviceDictCount * sizeof(CFPropertyListRef), 0);
	}

	CFDictionaryGetKeysAndValues(serviceDict, NULL, vals);
	serviceArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);

	for (CFIndex idx=0; idx < serviceDictCount; idx++) {
		serviceEntity = vals[idx];
		if (isA_CFDictionary(serviceEntity) == FALSE) {
			continue;
		}
		CFArrayAppendValue(serviceArray, serviceEntity);
	}

	serviceArrayCount = CFArrayGetCount(serviceArray);

	if (expectedServiceDictCount > (sizeof(expected_vals_q) / sizeof(CFTypeRef))) {
		expected_vals = CFAllocatorAllocate(NULL, expectedServiceDictCount, 0);
	}

	CFDictionaryGetKeysAndValues(expectedServiceDict, NULL, expected_vals);
	expectedServiceArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);

	for (CFIndex idx = 0; idx < expectedServiceDictCount; idx++) {
		serviceEntity = expected_vals[idx];

		if (isA_CFDictionary(serviceEntity) == FALSE) {
			continue;
		}
		CFArrayAppendValue(expectedServiceArray, serviceEntity);
	}
	expectedServiceArrayCount = CFArrayGetCount(expectedServiceArray);

	if (serviceArrayCount != expectedServiceArrayCount) {
		goto done;
	}

	for (CFIndex idx = 0; idx < expectedServiceArrayCount; idx++) {
		foundMatch = FALSE;
		expectedServiceEntity = CFArrayGetValueAtIndex(expectedServiceArray, idx);
		serviceArrayCount = CFArrayGetCount(serviceArray);

		for (CFIndex idx2 = 0; idx2 < serviceArrayCount; idx2++) {
			serviceEntity = CFArrayGetValueAtIndex(serviceArray, idx2);

			if (CFEqual(expectedServiceEntity, serviceEntity) == TRUE) {
				foundMatch = TRUE;
				break;
			}
		}

		if (foundMatch == FALSE) {
			break;
		}
	}

	success = foundMatch;
done:
	if (vals != vals_q) {
		CFAllocatorDeallocate(NULL, vals);
	}
	if (expected_vals != expected_vals_q) {
		CFAllocatorDeallocate(NULL, expected_vals);
	}
	return success;
}

static Boolean
_SCNetworkMigrationAreNetworkInterfaceConfigurationsIdentical (SCPreferencesRef configNetworkInterfacePref, SCPreferencesRef expectedNetworkInterfacePref)
{
	CFDictionaryRef expectedInterfaceEntity = NULL;
	CFArrayRef expectedInterfaceList = NULL;
	CFIndex expectedInterfaceListCount;
	Boolean foundMatch = FALSE;
	CFDictionaryRef interfaceEntity = NULL;
	CFArrayRef interfaceList = NULL;
	CFIndex interfaceListCount;
	CFMutableArrayRef interfaceListMutable = NULL;
	Boolean success = FALSE;

	interfaceList = SCPreferencesGetValue(configNetworkInterfacePref, INTERFACES);
	if (isA_CFArray(interfaceList) == NULL) {
		goto done;
	}
	interfaceListMutable = CFArrayCreateMutableCopy(NULL, 0, interfaceList);
	interfaceListCount = CFArrayGetCount(interfaceListMutable);

	expectedInterfaceList = SCPreferencesGetValue(expectedNetworkInterfacePref, INTERFACES);
	if (isA_CFArray(expectedInterfaceList) == NULL) {
		goto done;
	}
	expectedInterfaceListCount = CFArrayGetCount(expectedInterfaceList);

	if (interfaceListCount != expectedInterfaceListCount) {
		goto done;
	}

	for (CFIndex idx = 0; idx < expectedInterfaceListCount; idx++) {
		foundMatch = FALSE;
		expectedInterfaceEntity = CFArrayGetValueAtIndex(expectedInterfaceList, idx);
		interfaceListCount = CFArrayGetCount(interfaceListMutable);

		for (CFIndex idx2 = 0; idx2 < interfaceListCount; idx2++) {
			interfaceEntity = CFArrayGetValueAtIndex(interfaceList, idx2);
			if (CFEqual(expectedInterfaceEntity, interfaceEntity) == TRUE) {
				foundMatch = TRUE;
				break;
			}
		}
		if (foundMatch == FALSE) {
			break;
		}
	}
	success = foundMatch;

done:
	if (interfaceListMutable != NULL) {
		CFRelease(interfaceListMutable);
	}

	return success;
}

Boolean
_SCNetworkMigrationAreConfigurationsIdentical (CFURLRef configurationURL,
					       CFURLRef expectedConfigurationURL)
{
	CFURLRef baseConfigURL = NULL;
	CFURLRef baseExpectedConfigURL = NULL;
	CFURLRef configPreferencesURL = NULL;
	CFURLRef configNetworkInterfacesURL = NULL;
	SCPreferencesRef configPref = NULL;
	SCPreferencesRef configNetworkInterfacePref = NULL;
	SCPreferencesRef expectedConfigPref = NULL;
	SCPreferencesRef expectedNetworkInterfacePref = NULL;
	CFURLRef expectedNetworkInterfaceURL = NULL;
	CFURLRef expectedPreferencesURL = NULL;
	Boolean isIdentical = FALSE;
	CFStringRef networkInterfaceConfigString = NULL;
	CFStringRef networkInterfaceExpectedString = NULL;
	CFStringRef prefsConfigString = NULL;
	CFStringRef prefsExpectedString = NULL;
	char networkInterfaceConfigStr[PATH_MAX];
	char networkInterfaceExpectedStr[PATH_MAX];
	char prefsConfigStr[PATH_MAX];
	char prefsExpectedStr[PATH_MAX];
	
	if (configurationURL == NULL ||
	    expectedConfigurationURL == NULL) {
		return FALSE;
	}
	baseConfigURL = CFURLCreateWithFileSystemPathRelativeToBase(NULL, PREFS_DEFAULT_DIR_RELATIVE, kCFURLPOSIXPathStyle, TRUE, configurationURL);
	configPreferencesURL = CFURLCreateFromFileSystemRepresentationRelativeToBase(NULL, (const UInt8*) PREFS_DEFAULT_CONFIG_PLIST, sizeof(PREFS_DEFAULT_CONFIG_PLIST), FALSE, baseConfigURL);
        
        if (CFURLResourceIsReachable(configPreferencesURL, NULL) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationAreConfigurationsIdentical: preferences.plist file is not present."));
		goto done;
        }
	
	configNetworkInterfacesURL = CFURLCreateFromFileSystemRepresentationRelativeToBase(NULL, (const UInt8*)NETWORK_INTERFACES_PREFS_PLIST, sizeof(NETWORK_INTERFACES_PREFS_PLIST), FALSE, baseConfigURL);
	
	if (CFURLResourceIsReachable(configNetworkInterfacesURL, NULL) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationAreConfigurationsIdentical: NetworkInterfaces.plist file is not present."));
		goto done;
	}
	
	if (CFURLGetFileSystemRepresentation(configPreferencesURL, TRUE, (UInt8*)prefsConfigStr, sizeof(prefsConfigStr)) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationAreConfigurationsIdentical: Could not extract preferences information"));
		goto done;
	}
	if (CFURLGetFileSystemRepresentation(configNetworkInterfacesURL, TRUE, (UInt8*)networkInterfaceConfigStr, sizeof(networkInterfaceConfigStr)) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationAreConfigurationsIdentical: Could not extract network interfaces information"));
		goto done;
	}
	
	baseExpectedConfigURL = CFURLCreateWithFileSystemPathRelativeToBase(NULL, PREFS_DEFAULT_DIR_RELATIVE, kCFURLPOSIXPathStyle, TRUE, expectedConfigurationURL);
	expectedPreferencesURL = CFURLCreateFromFileSystemRepresentationRelativeToBase(NULL, (const UInt8*)PREFS_DEFAULT_CONFIG_PLIST, sizeof(PREFS_DEFAULT_CONFIG_PLIST), FALSE, baseExpectedConfigURL);
	
	if (CFURLResourceIsReachable(expectedPreferencesURL, NULL) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationAreConfigurationsIdentical: preferences.plist file is not present in the expected configuration."));
		goto done;
	}
	
	expectedNetworkInterfaceURL = CFURLCreateFromFileSystemRepresentationRelativeToBase(NULL, (const UInt8*)NETWORK_INTERFACES_PREFS_PLIST, sizeof(NETWORK_INTERFACES_PREFS_PLIST), FALSE, baseExpectedConfigURL);
	
	if (CFURLResourceIsReachable(expectedNetworkInterfaceURL, NULL) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationAreConfigurationsIdentical: NetworkInterfaces.plist file is not present in the expected configuration."));
		goto done;
	}
	
	if (CFURLGetFileSystemRepresentation(expectedPreferencesURL, TRUE, (UInt8*)prefsExpectedStr, sizeof(prefsExpectedStr)) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationAreConfigurationsIdentical: Could not extract preferences information"));
		goto done;
	}
	if (CFURLGetFileSystemRepresentation(expectedNetworkInterfaceURL, TRUE, (UInt8*)networkInterfaceExpectedStr, sizeof(networkInterfaceExpectedStr)) == FALSE) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationAreConfigurationsIdentical: Could not extract network interfaces information"));
		goto done;
	}
	
	prefsConfigString = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), prefsConfigStr);
	networkInterfaceConfigString = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), networkInterfaceConfigStr);
	prefsExpectedString = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), prefsExpectedStr);
	networkInterfaceExpectedString = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), networkInterfaceExpectedStr);
	
	configPref = SCPreferencesCreate(NULL, PLUGIN_ID, prefsConfigString);
	expectedConfigPref = SCPreferencesCreate(NULL, PLUGIN_ID, prefsExpectedString);
	configNetworkInterfacePref = SCPreferencesCreate(NULL, PLUGIN_ID, networkInterfaceConfigString);
	expectedNetworkInterfacePref = SCPreferencesCreate(NULL, PLUGIN_ID, networkInterfaceExpectedString);
done:
	if (configPref == NULL ||
	    expectedConfigPref == NULL ||
	    configNetworkInterfacePref == NULL ||
	    expectedNetworkInterfacePref == NULL) {
		SCLog(_sc_debug, LOG_NOTICE, CFSTR("_SCNetworkMigrationAreConfigurationsIdentical: One of the preferences is NULL"));
		isIdentical = FALSE;
	}
	else {
		isIdentical = (_SCNetworkMigrationAreServicesIdentical(configPref, expectedConfigPref) &&
			       _SCNetworkMigrationAreNetworkInterfaceConfigurationsIdentical(configNetworkInterfacePref, expectedNetworkInterfacePref));
	}
	if (baseConfigURL != NULL) {
		CFRelease(baseConfigURL);
	}
	if (configPreferencesURL != NULL) {
		CFRelease(configPreferencesURL);
	}
	if (configNetworkInterfacesURL != NULL) {
		CFRelease(configNetworkInterfacesURL);
	}
	if (baseExpectedConfigURL != NULL) {
		CFRelease(baseExpectedConfigURL);
	}
	if (expectedPreferencesURL != NULL) {
		CFRelease(expectedPreferencesURL);
	}
	if (expectedNetworkInterfaceURL != NULL) {
		CFRelease(expectedNetworkInterfaceURL);
	}
	if (prefsConfigString != NULL) {
		CFRelease(prefsConfigString);
	}
	if (networkInterfaceConfigString != NULL) {
		CFRelease(networkInterfaceConfigString);
	}
	if (prefsExpectedString != NULL) {
		CFRelease(prefsExpectedString);
	}
	if (networkInterfaceExpectedString != NULL) {
		CFRelease(networkInterfaceExpectedString);
	}
	if (configPref != NULL) {
		CFRelease(configPref);
	}
	if (expectedConfigPref != NULL) {
		CFRelease(expectedConfigPref);
	}
	if (configNetworkInterfacePref != NULL) {
		CFRelease(configNetworkInterfacePref);
	}
	if (expectedNetworkInterfacePref != NULL) {
		CFRelease(expectedNetworkInterfacePref);
	}
	return isIdentical;
}

CFArrayRef
_SCNetworkConfigurationCopyMigrationRemovePaths	(CFArrayRef	targetPaths,
                                                 CFURLRef	targetDir)
{
	CFURLRef affectedURL;
	char filePath[PATH_MAX];
	CFURLRef targetFile;
	CFMutableArrayRef toBeRemoved = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
	
	for (CFIndex idx = 0; idx < CFArrayGetCount(targetPaths); idx++) {
		affectedURL = CFArrayGetValueAtIndex(targetPaths, idx);
		
		if (CFURLGetFileSystemRepresentation(affectedURL, TRUE, (UInt8*)filePath, sizeof(filePath)) == FALSE) {
			SCLog(_sc_debug, LOG_NOTICE, CFSTR("filesToBeRemoved: Could not get file system representation"));
			continue;
		}
		targetFile = CFURLCreateFromFileSystemRepresentationRelativeToBase(NULL, (const UInt8*)filePath,
		strnlen(filePath, sizeof(filePath)), FALSE, targetDir);
		
		if (CFURLResourceIsReachable(targetFile, NULL) == FALSE) {
			CFArrayAppendValue(toBeRemoved, affectedURL);
		}
		CFRelease(targetFile);
	}
	// If number of files to be removed is 0, return NULL
	if (CFArrayGetCount(toBeRemoved) == 0) {
		CFRelease(toBeRemoved);
		toBeRemoved = NULL;
	}
	return toBeRemoved;
}