/*
- * Copyright (c) 2000-2008, 2010, 2012-2016 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2008, 2010, 2012-2020 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <TargetConditionals.h>
-#include <fcntl.h>
-#include <net/if.h>
#include <sys/types.h>
-#include <sys/stat.h>
#include <unistd.h>
-
-#define SC_LOG_HANDLE __log_PreferencesMonitor()
+#define SC_LOG_HANDLE __log_PreferencesMonitor
+#define SC_LOG_HANDLE_TYPE static
#include <SystemConfiguration/SystemConfiguration.h>
#include <SystemConfiguration/SCPrivate.h>
#include <SystemConfiguration/SCValidation.h>
+#include "SCNetworkConfigurationInternal.h"
#include "plugin_shared.h"
-#include <CommonCrypto/CommonDigest.h>
-
-
/* globals */
static SCPreferencesRef prefs = NULL;
static SCDynamicStoreRef store = NULL;
/* InterfaceNamer[.plugin] monitoring globals */
-Boolean haveConfiguration = FALSE;
+static CFMutableArrayRef excluded_interfaces = NULL; // of SCNetworkInterfaceRef
+static CFMutableArrayRef excluded_names = NULL; // of CFStringRef (BSD name)
+static Boolean haveConfiguration = FALSE;
static CFStringRef namerKey = NULL;
-static CFArrayRef preconfigured = NULL;
+static CFMutableArrayRef preconfigured_interfaces= NULL; // of SCNetworkInterfaceRef
+static CFMutableArrayRef preconfigured_names = NULL; // of CFStringRef (BSD name)
/* KernelEventMonitor[.plugin] monitoring globals */
static CFStringRef interfacesKey = NULL;
static CFMutableArrayRef removedPrefsKeys; /* old prefs keys to be removed */
static Boolean rofs = FALSE;
-static Boolean restorePrefs = FALSE;
#define MY_PLUGIN_NAME "PreferencesMonitor"
#define MY_PLUGIN_ID CFSTR("com.apple.SystemConfiguration." MY_PLUGIN_NAME)
static os_log_t
-__log_PreferencesMonitor()
+__log_PreferencesMonitor(void)
{
static os_log_t log = NULL;
}
-static Boolean
-restorePreferences()
+static void
+savePastConfiguration(CFStringRef old_model)
{
- Boolean ok = FALSE;
- CFStringRef currentModel = NULL;
- CFMutableStringRef modelPrefixStr = NULL;
- CFArrayRef keyList = NULL;
- CFIndex keyListCount;
- CFIndex idx;
- Boolean modified = FALSE;
- int sc_status = kSCStatusFailed;
-
- while (TRUE) {
- ok = SCPreferencesLock(prefs, TRUE);
- if (ok) {
- break;
- }
-
- sc_status = SCError();
- if (sc_status == kSCStatusStale) {
- SCPreferencesSynchronize(prefs);
- } else {
- SC_log(LOG_NOTICE, "Could not acquire network configuration lock: %s",
- SCErrorString(sc_status));
- return FALSE;
- }
- }
-
- keyList = SCPreferencesCopyKeyList(prefs);
- if (keyList == NULL) {
- goto error;
- }
-
- currentModel = _SC_hw_model(FALSE);
- if (currentModel == NULL) {
- goto error;
- }
-
- /* Create "model:" string for prefix-check */
- modelPrefixStr = CFStringCreateMutableCopy(NULL, 0, currentModel);
- CFStringAppend(modelPrefixStr, CFSTR(":"));
+ CFDictionaryRef system;
- keyListCount = CFArrayGetCount(keyList);
- for (idx = 0; idx < keyListCount; idx++) {
- CFStringRef existingKey = CFArrayGetValueAtIndex(keyList, idx);
- CFStringRef key;
- CFArrayRef splitKey = NULL;
- CFPropertyListRef value;
-
- if (isA_CFString(existingKey) == NULL) {
- continue;
- }
-
- if (!CFStringHasPrefix(existingKey, modelPrefixStr)) {
- continue;
- }
-
- splitKey = CFStringCreateArrayBySeparatingStrings(NULL, existingKey, CFSTR(":"));
- key = CFArrayGetValueAtIndex(splitKey, 1);
- value = SCPreferencesGetValue(prefs, existingKey);
- SCPreferencesSetValue(prefs, key, value);
- SCPreferencesRemoveValue(prefs, existingKey);
- modified = TRUE;
- CFRelease(splitKey);
- }
-
- if (modified) {
- SCPreferencesRef ni_prefs = NULL;
- ni_prefs = SCPreferencesCreate(NULL, MY_PLUGIN_ID, CFSTR("NetworkInterfaces.plist"));
- if (ni_prefs == NULL) {
- goto error;
- }
-
- ok = _SCNetworkConfigurationCheckValidityWithPreferences(prefs, ni_prefs, NULL);
- CFRelease(ni_prefs);
-
- //Commit the changes only if prefs files valid
- if (ok) {
- if (!SCPreferencesCommitChanges(prefs)) {
- if (SCError() != EROFS) {
- SC_log(LOG_NOTICE, "SCPreferencesCommitChanges() failed: %s",
- SCErrorString(SCError()));
- }
- goto error;
-
- }
-
- (void) SCPreferencesApplyChanges(prefs);
- }
+ // save "/System" (e.g. host names)
+ system = SCPreferencesGetValue(prefs, kSCPrefSystem);
+ if (system != NULL) {
+ CFRetain(system);
}
-error:
- (void) SCPreferencesUnlock(prefs);
+ // save the [previous devices] configuration
+ __SCNetworkConfigurationSaveModel(prefs, old_model);
- if (keyList != NULL) {
- CFRelease(keyList);
- }
- if (modelPrefixStr != NULL) {
- CFRelease(modelPrefixStr);
+ if (system != NULL) {
+ // and retain "/System" (e.g. host names)
+ SCPreferencesSetValue(prefs, kSCPrefSystem, system);
+ CFRelease(system);
}
- return modified;
+ return;
}
+
static Boolean
establishNewPreferences()
{
SCNetworkSetRef current = NULL;
CFStringRef new_model;
Boolean ok = FALSE;
+ CFStringRef old_model;
int sc_status = kSCStatusFailed;
SCNetworkSetRef set = NULL;
Boolean updated = FALSE;
}
}
- /* Ensure that the preferences has the new model */
+ // check if we need to regenerate the configuration for a new model
+ old_model = SCPreferencesGetValue(prefs, MODEL);
new_model = _SC_hw_model(FALSE);
-
- /* Need to regenerate the new configuration for new model */
- if (new_model != NULL) {
- CFStringRef old_model;
-
- old_model = SCPreferencesGetValue(prefs, MODEL);
- if ((old_model != NULL) && !_SC_CFEqual(old_model, new_model)) {
- CFIndex count;
- CFIndex index;
- CFArrayRef keys;
-
- keys = SCPreferencesCopyKeyList(prefs);
- count = (keys != NULL) ? CFArrayGetCount(keys) : 0;
- // if new hardware
- for (index = 0; index < count; index++) {
- CFStringRef existing_key;
-
- existing_key = CFArrayGetValueAtIndex(keys, index);
- if (isA_CFString(existing_key) != NULL) {
- CFStringRef new_key;
- CFPropertyListRef value;
-
- /* If it already contains a Model
- or if it already contains a MODEL:KEY key skip it*/
- if (CFEqual(existing_key, MODEL)
- || CFStringFind(existing_key, CFSTR(":"), 0).location
- != kCFNotFound) {
- continue;
- }
-
- value = SCPreferencesGetValue(prefs, existing_key);
-
- /* Create a new key as OLD_MODEL:OLD_KEY */
- new_key = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@:%@"),
- old_model, existing_key);
- SCPreferencesSetValue(prefs, new_key, value);
- if (!CFEqual(existing_key, kSCPrefSystem)) {
- /* preserve existing host names */
- SCPreferencesRemoveValue(prefs, existing_key);
- }
- CFRelease(new_key);
- }
- }
-
- if (keys != NULL) {
- CFRelease(keys);
- }
- }
- /* Set the new model */
- SCPreferencesSetValue(prefs, MODEL, new_model);
+ if ((old_model != NULL) && !_SC_CFEqual(old_model, new_model)) {
+ SC_log(LOG_NOTICE, "Hardware model changed\n"
+ " created on \"%@\"\n"
+ " now on \"%@\"",
+ old_model,
+ new_model);
+
+ // save (and clean) the configuration that was created for "other" hardware
+ savePastConfiguration(old_model);
}
current = SCNetworkSetCopyCurrent(prefs);
}
if (!ok) {
- SC_log(LOG_NOTICE, "Could not establish network configuration: %s",
- SCErrorString(sc_status));
+ if (sc_status == kSCStatusOK) {
+ SC_log(LOG_NOTICE, "Network configuration not updated");
+ } else {
+ SC_log(LOG_NOTICE, "Could not establish network configuration: %s",
+ SCErrorString(sc_status));
+ }
}
(void)SCPreferencesUnlock(prefs);
}
-
-
static Boolean
-previousConfigurationAvailable()
+findInterfaces(CFArrayRef interfaces, CFMutableArrayRef *matched_interfaces, CFMutableArrayRef *matched_names)
{
- CFStringRef backupKey = NULL;
- CFStringRef currentModel = NULL;
- CFPropertyListRef properties = NULL;
+ CFIndex n;
+ CFIndex nx = 0;
+ Boolean updated = FALSE;
- currentModel = _SC_hw_model(FALSE);
- if (currentModel == NULL) {
- goto done;
+ // start clean
+ if (*matched_interfaces != NULL) {
+ CFRelease(*matched_interfaces);
+ *matched_interfaces = NULL;
+ }
+ if (*matched_names != NULL) {
+ nx = CFArrayGetCount(*matched_names);
+ CFRelease(*matched_names);
+ *matched_names = NULL;
}
- /* Currently relying only if a backup of "Sets" is present */
- backupKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@:Sets"), currentModel);
- properties = SCPreferencesGetValue(prefs, backupKey);
- CFRelease(backupKey);
-done:
- return (properties != NULL);
+ n = (interfaces != NULL) ? CFArrayGetCount(interfaces) : 0;
+ for (CFIndex i = 0; i < n; i++) {
+ CFStringRef bsdName = CFArrayGetValueAtIndex(interfaces, i);
+ SCNetworkInterfaceRef interface;
+
+ for (int retry = 0; retry < 10; retry++) {
+ if (retry != 0) {
+ // add short delay (before retry)
+ usleep(20 * 1000); // 20ms
+ }
+
+ interface = _SCNetworkInterfaceCreateWithBSDName(NULL, bsdName, kIncludeNoVirtualInterfaces);
+ if (interface == NULL) {
+ SC_log(LOG_ERR, "could not create network interface for %@", bsdName);
+ } else if (_SCNetworkInterfaceGetIOPath(interface) == NULL) {
+ SC_log(LOG_ERR, "could not get IOPath for %@", bsdName);
+ CFRelease(interface);
+ interface = NULL;
+ }
+
+ if (interface == NULL) {
+ // if SCNetworkInterface not [currently] available
+ continue;
+ }
+
+ // keep track of the interface name (quicker than having to iterate the list
+ // of SCNetworkInterfaces, extract the name, and compare).
+ if (*matched_names == NULL) {
+ *matched_names = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ }
+ CFArrayAppendValue(*matched_names, bsdName);
+
+ if (*matched_interfaces == NULL) {
+ *matched_interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ }
+ CFArrayAppendValue(*matched_interfaces, interface);
+ CFRelease(interface);
+
+ updated = TRUE;
+ break;
+ }
+ }
+
+ // check if all interfaces were detached
+ n = (*matched_names != NULL) ? CFArrayGetCount(*matched_names) : 0;
+ if ((nx > 0) && (n == 0)) {
+ updated = TRUE;
+ }
+
+ return updated;
}
static void
storeCallback(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info)
{
+#pragma unused(info)
CFDictionaryRef dict;
- CFArrayRef interfaces = NULL;
Boolean quiet = FALSE;
Boolean timeout = FALSE;
Boolean updated = FALSE;
- /*
- * Capture/process KernelEventMonitor[.bundle] info
- * 1. get list of active network interfaces
- */
- dict = SCDynamicStoreCopyValue(store, interfacesKey);
- if (dict != NULL) {
- if (isA_CFDictionary(dict)) {
- interfaces = CFDictionaryGetValue(dict, kSCPropNetInterfaces);
- interfaces = isA_CFArray(interfaces);
- if (interfaces != NULL) {
- CFRetain(interfaces);
- }
- }
-
- CFRelease(dict);
- }
-
/*
* Capture/process InterfaceNamer[.bundle] info
* 1. check if IORegistry "quiet", "timeout"
- * 2. get list of named pre-configured interfaces
- * 3. merge list of active interfaces (from KEV) with the
- * list of preconfigured interfaces.
+ * 2. update list of excluded interfaces (e.g. those requiring that
+ * the attached host be trusted)
+ * 3. update list of named pre-configured interfaces
*/
dict = SCDynamicStoreCopyValue(store, namerKey);
if (dict != NULL) {
if (isA_CFDictionary(dict)) {
- CFArrayRef cur_preconfigured;
- CFMutableArrayRef new_preconfigured = NULL;
+ CFArrayRef excluded;
+ CFArrayRef preconfigured;
if (CFDictionaryContainsKey(dict, kInterfaceNamerKey_Quiet)) {
quiet = TRUE;
timeout = TRUE;
}
- cur_preconfigured = CFDictionaryGetValue(dict, kInterfaceNamerKey_PreConfiguredInterfaces);
- cur_preconfigured = isA_CFArray(cur_preconfigured);
- if ((cur_preconfigured != NULL) && (interfaces != NULL)) {
- CFIndex i;
- CFIndex n;
- CFRange r = CFRangeMake(0, CFArrayGetCount(interfaces));
-
- n = CFArrayGetCount(cur_preconfigured);
- for (i = 0; i < n; i++) {
- CFStringRef bsdName;
-
- bsdName = CFArrayGetValueAtIndex(cur_preconfigured, i);
- if (!CFArrayContainsValue(interfaces, r, bsdName)) {
- // if interface not currently active
- continue;
- }
+ excluded = CFDictionaryGetValue(dict, kInterfaceNamerKey_ExcludedInterfaces);
+ excluded = isA_CFArray(excluded);
+ if (!_SC_CFEqual(excluded, excluded_names)) {
+ Boolean excluded_updated;
- if (new_preconfigured == NULL) {
- new_preconfigured = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ excluded_updated = findInterfaces(excluded, &excluded_interfaces, &excluded_names);
+ if (excluded_updated) {
+ CFStringRef interfaces = CFSTR("<empty>");
+
+ // report [updated] pre-configured interfaces
+ if (excluded_names != NULL) {
+ interfaces = CFStringCreateByCombiningStrings(NULL, excluded_names, CFSTR(","));
+ } else {
+ CFRetain(interfaces);
}
- CFArrayAppendValue(new_preconfigured, bsdName);
+ SC_log(LOG_INFO, "excluded interface list changed: %@", interfaces);
+ CFRelease(interfaces);
+
+ updated = TRUE;
}
}
- if (!_SC_CFEqual(preconfigured, new_preconfigured)) {
- SC_log(LOG_INFO, "pre-configured interface list changed");
+ preconfigured = CFDictionaryGetValue(dict, kInterfaceNamerKey_PreConfiguredInterfaces);
+ preconfigured = isA_CFArray(preconfigured);
+ if (!_SC_CFEqual(preconfigured, preconfigured_names)) {
+ Boolean preconfigured_updated;
- if (preconfigured != NULL) {
- CFRelease(preconfigured);
- }
- if (new_preconfigured != NULL) {
- CFRetain(new_preconfigured);
- }
- preconfigured = new_preconfigured;
+ preconfigured_updated = findInterfaces(preconfigured, &preconfigured_interfaces, &preconfigured_names);
+ if (preconfigured_updated) {
+ CFStringRef interfaces = CFSTR("<empty>");
- updated = TRUE;
- }
+ // report [updated] pre-configured interfaces
+ if (preconfigured_names != NULL) {
+ interfaces = CFStringCreateByCombiningStrings(NULL, preconfigured_names, CFSTR(","));
+ } else {
+ CFRetain(interfaces);
+ }
+ SC_log(LOG_INFO, "pre-configured interface list changed: %@", interfaces);
+ CFRelease(interfaces);
- if (new_preconfigured != NULL) {
- CFRelease(new_preconfigured);
+ updated = TRUE;
+ }
}
}
CFRelease(dict);
}
- if (interfaces != NULL) {
- CFRelease(interfaces);
- }
-
if (!haveConfiguration && (quiet || timeout)) {
static int logged = 0;
(void) establishNewPreferences();
- if (restorePrefs) {
- (void) restorePreferences();
- restorePrefs = FALSE;
- }
-
if (timeout && (logged++ == 0)) {
SC_log(LOG_ERR, "Network configuration creation timed out waiting for IORegistry");
}
static void
updateCache(const void *key, const void *value, void *context)
{
+#pragma unused(context)
CFStringRef configKey = (CFStringRef)key;
CFPropertyListRef configData = (CFPropertyListRef)value;
CFPropertyListRef cacheData;
}
-static CF_RETURNS_RETAINED SCNetworkServiceRef
-copyInterfaceService(SCNetworkSetRef set, CFStringRef matchName)
+static void
+excludeConfigurations(SCPreferencesRef prefs)
{
- CFIndex i;
- CFIndex n;
- SCNetworkServiceRef service = NULL;
- CFArrayRef services;
+ Boolean ok;
+ CFRange range;
+ CFArrayRef services;
+ SCNetworkSetRef set;
- services = SCNetworkSetCopyServices(set);
- assert(services != NULL);
+ range = CFRangeMake(0,
+ (excluded_names != NULL) ? CFArrayGetCount(excluded_names) : 0);
+ if (range.length == 0) {
+ // if no [excluded] interfaces
+ return;
+ }
- n = CFArrayGetCount(services);
- for (i = 0; i < n; i++) {
- SCNetworkInterfaceRef interface;
+ set = SCNetworkSetCopyCurrent(prefs);
+ if (set == NULL) {
+ // if no current set
+ return;
+ }
+
+ /*
+ * Check for (and remove) any network services associated with
+ * an excluded interface from the prefs.
+ */
+ services = SCNetworkSetCopyServices(set);
+ if (services != NULL) {
+ CFIndex n;
- service = CFArrayGetValueAtIndex(services, i);
- interface = SCNetworkServiceGetInterface(service);
- if (interface != NULL) {
+ n = CFArrayGetCount(services);
+ for (CFIndex i = 0; i < n; i++) {
CFStringRef bsdName;
+ SCNetworkInterfaceRef interface;
+ SCNetworkServiceRef service;
+
+ service = CFArrayGetValueAtIndex(services, i);
+
+ interface = SCNetworkServiceGetInterface(service);
+ if (interface == NULL) {
+ // if no interface
+ continue;
+ }
bsdName = SCNetworkInterfaceGetBSDName(interface);
- if (_SC_CFEqual(bsdName, matchName)) {
- // if match
- CFRetain(service);
- break;
+ if (bsdName == NULL) {
+ // if no interface name
+ continue;
}
- }
- service = NULL;
- }
+ if (!CFArrayContainsValue(excluded_names, range, bsdName)) {
+ // if not excluded
+ continue;
+ }
- CFRelease(services);
- return service;
-}
+ // remove [excluded] network service from the prefs
+ SC_log(LOG_NOTICE, "excluding network service for %@", bsdName);
+ ok = SCNetworkSetRemoveService(set, service);
+ if (!ok) {
+ SC_log(LOG_ERR, "SCNetworkSetRemoveService() failed: %s",
+ SCErrorString(SCError()));
+ }
+ }
+ CFRelease(services);
+ }
-static CF_RETURNS_RETAINED CFStringRef
-copyInterfaceUUID(CFStringRef bsdName)
-{
- union {
- unsigned char sha1_bytes[CC_SHA1_DIGEST_LENGTH];
- CFUUIDBytes uuid_bytes;
- } bytes;
- CC_SHA1_CTX ctx;
- char if_name[IF_NAMESIZE];
- CFUUIDRef uuid;
- CFStringRef uuid_str;
-
- // start with interface name
- bzero(&if_name, sizeof(if_name));
- (void) _SC_cfstring_to_cstring(bsdName,
- if_name,
- sizeof(if_name),
- kCFStringEncodingASCII);
-
- // create SHA1 hash
- bzero(&bytes, sizeof(bytes));
- CC_SHA1_Init(&ctx);
- CC_SHA1_Update(&ctx,
- if_name,
- sizeof(if_name));
- CC_SHA1_Final(bytes.sha1_bytes, &ctx);
-
- // create UUID string
- uuid = CFUUIDCreateFromUUIDBytes(NULL, bytes.uuid_bytes);
- uuid_str = CFUUIDCreateString(NULL, uuid);
- CFRelease(uuid);
-
- return uuid_str;
+ CFRelease(set);
+ return;
}
{
Boolean ok;
CFRange range;
+ CFArrayRef services;
SCNetworkSetRef set;
Boolean updated = FALSE;
- range.length = (preconfigured != NULL) ? CFArrayGetCount(preconfigured) : 0;
+ range = CFRangeMake(0,
+ (preconfigured_names != NULL) ? CFArrayGetCount(preconfigured_names) : 0);
if (range.length == 0) {
- // if no [preconfigured] interfaces
+ // if no [pre-configured] interfaces
return;
}
- range.location = 0;
set = SCNetworkSetCopyCurrent(prefs);
- if (set != NULL) {
- CFArrayRef services;
-
- /*
- * Check for (and remove) and network services associated with
- * a pre-configured interface from the prefs.
- */
- services = SCNetworkSetCopyServices(set);
- if (services != NULL) {
- CFIndex n;
-
- n = CFArrayGetCount(services);
- for (CFIndex i = 0; i < n; i++) {
- CFStringRef bsdName;
- SCNetworkInterfaceRef interface;
- SCNetworkServiceRef service;
-
- service = CFArrayGetValueAtIndex(services, i);
-
- interface = SCNetworkServiceGetInterface(service);
- if (interface == NULL) {
- // if no interface
- continue;
- }
-
- bsdName = SCNetworkInterfaceGetBSDName(interface);
- if (bsdName == NULL) {
- // if no interface name
- continue;
- }
-
- if (!CFArrayContainsValue(preconfigured, range, bsdName)) {
- // if not preconfigured
- continue;
- }
-
- // remove [preconfigured] network service from the prefs
- SC_log(LOG_NOTICE, "removing network service for %@", bsdName);
- SCNetworkServiceRemove(service);
- updated = TRUE;
- }
-
- CFRelease(services);
- }
+ if (set == NULL) {
+ // if no current set
+ return;
+ }
- if (updated) {
- // commit the updated prefs ... but don't apply
- ok = SCPreferencesCommitChanges(prefs);
- if (!ok) {
- if (SCError() != EROFS) {
- SC_log(LOG_NOTICE, "SCPreferencesCommitChanges() failed: %s",
- SCErrorString(SCError()));
- }
- }
- }
+ /*
+ * Check for (and remove) any network services associated with
+ * a pre-configured interface from the prefs.
+ */
+ services = SCNetworkServiceCopyAll(prefs);
+ if (services != NULL) {
+ CFIndex n;
- /*
- * Now, add a new network service for each pre-configured interface
- */
- for (CFIndex i = 0; i < range.length; i++) {
+ n = CFArrayGetCount(services);
+ for (CFIndex i = 0; i < n; i++) {
CFStringRef bsdName;
SCNetworkInterfaceRef interface;
SCNetworkServiceRef service;
- bsdName = CFArrayGetValueAtIndex(preconfigured, i);
- interface = _SCNetworkInterfaceCreateWithBSDName(NULL, bsdName, kIncludeNoVirtualInterfaces);
+ service = CFArrayGetValueAtIndex(services, i);
+
+ interface = SCNetworkServiceGetInterface(service);
if (interface == NULL) {
- SC_log(LOG_ERR, "could not create network interface for %@", bsdName);
+ // if no interface
continue;
}
- if (_SCNetworkInterfaceGetIOPath(interface) == NULL) {
- // if no [real] interface exists
- CFRelease(interface);
+ bsdName = SCNetworkInterfaceGetBSDName(interface);
+ if (bsdName == NULL) {
+ // if no interface name
continue;
}
- ok = SCNetworkSetEstablishDefaultInterfaceConfiguration(set, interface);
- CFRelease(interface);
- if (!ok) {
- SC_log(LOG_ERR, "could not create network service for %@", bsdName);
+ if (!CFArrayContainsValue(preconfigured_names, range, bsdName)) {
+ // if not preconfigured
continue;
}
- service = copyInterfaceService(set, bsdName);
- if (service != NULL) {
- CFStringRef serviceID;
-
- serviceID = copyInterfaceUUID(bsdName);
- if (serviceID != NULL) {
- ok = _SCNetworkServiceSetServiceID(service, serviceID);
- CFRelease(serviceID);
- if (!ok) {
- SC_log(LOG_ERR, "_SCNetworkServiceSetServiceID() failed: %s",
- SCErrorString(SCError()));
- // ... and keep whatever random UUID was created for the service
- }
- } else {
- SC_log(LOG_ERR, "could not create serviceID for %@", bsdName);
- // ... and we'll use whatever random UUID was created for the service
- }
+ // remove [preconfigured] network service from the prefs
+ SC_log(LOG_NOTICE, "removing network service for %@", bsdName);
+ ok = SCNetworkServiceRemove(service);
+ if (!ok) {
+ SC_log(LOG_ERR, "SCNetworkServiceRemove() failed: %s",
+ SCErrorString(SCError()));
+ }
+ updated = TRUE;
+ }
- SC_log(LOG_INFO, "network service %@ added for %@",
- SCNetworkServiceGetServiceID(service),
- bsdName);
+ CFRelease(services);
+ }
- CFRelease(service);
- } else {
- SC_log(LOG_ERR, "could not find network service for %@", bsdName);
+ if (updated) {
+ // commit the updated prefs ... but don't apply
+ ok = SCPreferencesCommitChanges(prefs);
+ if (!ok) {
+ if (SCError() != EROFS) {
+ SC_log(LOG_ERR, "SCPreferencesCommitChanges() failed: %s",
+ SCErrorString(SCError()));
}
}
+ }
- CFRelease(set);
+ /*
+ * Now, add a new network service for each pre-configured interface
+ */
+ for (CFIndex i = 0; i < range.length; i++) {
+ CFStringRef bsdName;
+ SCNetworkInterfaceRef interface = CFArrayGetValueAtIndex(preconfigured_interfaces, i);
+ SCNetworkServiceRef service;
+
+ bsdName = SCNetworkInterfaceGetBSDName(interface);
+
+ // create network service
+ service = _SCNetworkServiceCreatePreconfigured(prefs, interface);
+ if (service == NULL) {
+ continue;
+ }
+
+ // add network service to the current set
+ ok = SCNetworkSetAddService(set, service);
+ if (!ok) {
+ SC_log(LOG_ERR, "could not add service for \"%@\": %s",
+ bsdName,
+ SCErrorString(SCError()));
+ SCNetworkServiceRemove(service);
+ CFRelease(service);
+ continue;
+ }
+
+ SC_log(LOG_INFO, "network service %@ added for \"%@\"",
+ SCNetworkServiceGetServiceID(service),
+ bsdName);
+
+ CFRelease(service);
}
+ CFRelease(set);
return;
}
SCPreferencesNotification notificationType,
void *info)
{
- os_activity_t activity;
-
- activity = os_activity_create("processing [SC] preferences.plist changes",
- OS_ACTIVITY_CURRENT,
- OS_ACTIVITY_FLAG_DEFAULT);
- os_activity_scope(activity);
-
+#pragma unused(info)
#if !TARGET_OS_IPHONE
if ((notificationType & kSCPreferencesNotificationCommit) == kSCPreferencesNotificationCommit) {
SCNetworkSetRef current;
/* add any [Apple] pre-configured network services */
updatePreConfiguredConfiguration(prefs);
+ /* remove any excluded network services */
+ excludeConfigurations(prefs);
+
/* update SCDynamicStore (Setup:) */
updateSCDynamicStore(prefs);
done :
- os_release(activity);
-
return;
}
}
+#ifndef MAIN
+#define PREFERENCES_MONITOR_PLIST NULL
+#else // !MAIN
+#define PREFERENCES_MONITOR_PLIST CFSTR("/tmp/preferences.plist")
+#endif // !MAIN
+
+
__private_extern__
void
load_PreferencesMonitor(CFBundleRef bundle, Boolean bundleVerbose)
{
+#pragma unused(bundle)
+#pragma unused(bundleVerbose)
SC_log(LOG_DEBUG, "load() called");
SC_log(LOG_DEBUG, " bundle ID = %@", CFBundleGetIdentifier(bundle));
}
/* open a SCPreferences session */
-#ifndef MAIN
- prefs = SCPreferencesCreate(NULL, CFSTR("PreferencesMonitor.bundle"), NULL);
-#else // !MAIN
- prefs = SCPreferencesCreate(NULL, CFSTR("PreferencesMonitor.bundle"), CFSTR("/tmp/preferences.plist"));
-#endif // !MAIN
+ prefs = SCPreferencesCreateWithOptions(NULL,
+ MY_PLUGIN_ID,
+ PREFERENCES_MONITOR_PLIST,
+ NULL, // authorization
+ NULL);
if (prefs != NULL) {
Boolean need_update = FALSE;
- CFStringRef new_model;
+ CFStringRef new_model;
+ CFStringRef old_model;
+
+ // check if we need to update the configuration
+ __SCNetworkConfigurationUpgrade(&prefs, NULL, TRUE);
+ // check if we need to regenerate the configuration for a new model
+ old_model = SCPreferencesGetValue(prefs, MODEL);
new_model = _SC_hw_model(FALSE);
+ if ((old_model != NULL) && !_SC_CFEqual(old_model, new_model)) {
+ SC_log(LOG_NOTICE, "Hardware model changed\n"
+ " created on \"%@\"\n"
+ " now on \"%@\"",
+ old_model,
+ new_model);
- /* Need to regenerate the new configuration for new model */
- if (new_model != NULL) {
- CFStringRef old_model;
+ // save (and clean) the configuration that was created for "other" hardware
+ savePastConfiguration(old_model);
- old_model = SCPreferencesGetValue(prefs, MODEL);
- if (old_model != NULL && !_SC_CFEqual(old_model, new_model)) {
- // if new hardware
- need_update = TRUE;
- restorePrefs = previousConfigurationAvailable();
- }
+ // ... and we'll update the configuration later (when the IORegistry quiesces)
+ need_update = TRUE;
}
if (!need_update) {
int
main(int argc, char **argv)
{
- _sc_log = FALSE;
+ _sc_log = kSCLogDestinationFile;
_sc_verbose = (argc > 1) ? TRUE : FALSE;
load_PreferencesMonitor(CFBundleGetMainBundle(), (argc > 1) ? TRUE : FALSE);