__private_extern__ Boolean __setPrefsConfiguration(SCPreferencesRef prefs, CFStringRef path, CFDictionaryRef config, Boolean keepInactive) { CFDictionaryRef curConfig; CFMutableDictionaryRef newConfig = NULL; Boolean ok; if ((config != NULL) && !isA_CFDictionary(config)) { _SCErrorSet(kSCStatusInvalidArgument); return FALSE; } curConfig = SCPreferencesPathGetValue(prefs, path); if (config != NULL) { newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config); } if (keepInactive) { if (config == NULL) { newConfig = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); } if (isA_CFDictionary(curConfig) && CFDictionaryContainsKey(curConfig, kSCResvInactive)) { // if currently disabled CFDictionarySetValue(newConfig, kSCResvInactive, kCFBooleanTrue); } else { // if currently enabled CFDictionaryRemoveValue(newConfig, kSCResvInactive); } } // set new configuration if (_SC_CFEqual(curConfig, newConfig)) { // if no change if (newConfig != NULL) CFRelease(newConfig); ok = TRUE; } else if (newConfig != NULL) { // if new configuration (or we are preserving a disabled state) ok = SCPreferencesPathSetValue(prefs, path, newConfig); CFRelease(newConfig); } else { ok = SCPreferencesPathRemoveValue(prefs, path); if (!ok && (SCError() == kSCStatusNoKey)) { ok = TRUE; } } return ok; }
static SCBridgeInterfaceRef copyAutoBridgeInterface(SCPreferencesRef prefs, CFStringRef bridgeName) { SCBridgeInterfaceRef bridge = NULL; CFArrayRef interfaces; // exclude Bridge [member] interfaces interfaces = SCBridgeInterfaceCopyAll(prefs); if (interfaces != NULL) { CFIndex i; CFIndex n; n = CFArrayGetCount(interfaces); for (i = 0; i < n; i++) { SCBridgeInterfaceRef interface; CFStringRef name = NULL; CFDictionaryRef options; interface = CFArrayGetValueAtIndex(interfaces, i); options = SCBridgeInterfaceGetOptions(interface); if ((options != NULL) && CFDictionaryGetValueIfPresent(options, CFSTR("__AUTO__"), (const void **)&name) && _SC_CFEqual(name, bridgeName)) { bridge = interface; CFRetain(bridge); break; } } CFRelease(interfaces); } if (bridge == NULL) { bridge = SCBridgeInterfaceCreate(prefs); if (bridge != NULL) { CFMutableDictionaryRef newOptions; Boolean ok; newOptions = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionarySetValue(newOptions, CFSTR("__AUTO__"), bridgeName); ok = SCBridgeInterfaceSetOptions(bridge, newOptions); CFRelease(newOptions); if (!ok) { CFRelease(bridge); bridge = NULL; } } } return bridge; }
__private_extern__ Boolean __setPrefsEnabled(SCPreferencesRef prefs, CFStringRef path, Boolean enabled) { CFDictionaryRef curConfig; CFMutableDictionaryRef newConfig = NULL; Boolean ok = FALSE; // preserve current configuration curConfig = SCPreferencesPathGetValue(prefs, path); if (curConfig != NULL) { if (!isA_CFDictionary(curConfig)) { _SCErrorSet(kSCStatusFailed); return FALSE; } newConfig = CFDictionaryCreateMutableCopy(NULL, 0, curConfig); if (enabled) { // enable CFDictionaryRemoveValue(newConfig, kSCResvInactive); } else { // disable CFDictionarySetValue(newConfig, kSCResvInactive, kCFBooleanTrue); } } else { if (!enabled) { // disable newConfig = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionarySetValue(newConfig, kSCResvInactive, kCFBooleanTrue); } } // set new configuration if (_SC_CFEqual(curConfig, newConfig)) { // if no change if (newConfig != NULL) CFRelease(newConfig); ok = TRUE; } else if (newConfig != NULL) { // if updated configuration (or we are establishing as disabled) ok = SCPreferencesPathSetValue(prefs, path, newConfig); CFRelease(newConfig); } else { ok = SCPreferencesPathRemoveValue(prefs, path); if (!ok && (SCError() == kSCStatusNoKey)) { ok = TRUE; } } return ok; }
static CFArrayRef updateServices(CFArrayRef services, SCNetworkInterfaceRef interface) { CFStringRef bsdName; CFIndex i; CFIndex n; CFMutableArrayRef newServices; if (services == NULL) { return NULL; } bsdName = SCNetworkInterfaceGetBSDName(interface); newServices = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); n = CFArrayGetCount(services); for (i = 0; i < n; i++) { SCNetworkInterfaceRef interface; CFStringRef interfaceName; SCNetworkServiceRef newService; SCNetworkServiceRef service; CFStringRef serviceID; SCNetworkServicePrivateRef servicePrivate; service = CFArrayGetValueAtIndex(services, i); interface = SCNetworkServiceGetInterface(service); interfaceName = SCNetworkInterfaceGetBSDName(interface); if (!_SC_CFEqual(interfaceName, bsdName)) { // if not a match, retain CFArrayAppendValue(newServices, service); continue; } // if a match, update serviceID = SCNetworkServiceGetServiceID(service); servicePrivate = (SCNetworkServicePrivateRef)service; newService = SCNetworkServiceCopy(servicePrivate->prefs, serviceID); if (newService != NULL) { CFArrayAppendValue(newServices, newService); CFRelease(newService); } } return newServices; }
static void update_pref(SCPreferencesRef prefs, CFStringRef key, CFTypeRef newVal, Boolean *changed) { CFTypeRef curVal; curVal = SCPreferencesGetValue(prefs, key); if (!_SC_CFEqual(curVal, newVal)) { if (newVal != NULL) { SCPreferencesSetValue(prefs, key, newVal); } else { SCPreferencesRemoveValue(prefs, key); } *changed = TRUE; } return; }
__private_extern__ void load_PreferencesMonitor(CFBundleRef bundle, Boolean bundleVerbose) { Boolean initPrefs = TRUE; if (bundleVerbose) { _verbose = TRUE; } SCLog(_verbose, LOG_DEBUG, CFSTR("load() called")); SCLog(_verbose, LOG_DEBUG, CFSTR(" bundle ID = %@"), CFBundleGetIdentifier(bundle)); /* open a SCDynamicStore session to allow cache updates */ store = SCDynamicStoreCreate(NULL, CFSTR("PreferencesMonitor.bundle"), watchQuietCallback, NULL); if (store == NULL) { SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreCreate() failed: %s"), SCErrorString(SCError())); goto error; } /* 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 if (prefs != NULL) { Boolean need_update = FALSE; CFStringRef new_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)) { // if new hardware need_update = TRUE; } } if (need_update == FALSE) { SCNetworkSetRef current; current = SCNetworkSetCopyCurrent(prefs); if (current != NULL) { /* network configuration available, disable template creation */ initPrefs = FALSE; CFRelease(current); } } } else { SCLog(TRUE, LOG_ERR, CFSTR("SCPreferencesCreate() failed: %s"), SCErrorString(SCError())); goto error; } /* * register for change notifications. */ if (!SCPreferencesSetCallback(prefs, updateConfiguration, NULL)) { SCLog(TRUE, LOG_ERR, CFSTR("SCPreferencesSetCallBack() failed: %s"), SCErrorString(SCError())); goto error; } if (!SCPreferencesScheduleWithRunLoop(prefs, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)) { SCLog(TRUE, LOG_ERR, CFSTR("SCPreferencesScheduleWithRunLoop() failed: %s"), SCErrorString(SCError())); goto error; } /* * if no preferences, initialize with a template (now or * when IOKit has quiesced). */ if (initPrefs) { watchQuietEnable(); watchQuietCallback(store, NULL, NULL); } return; error : watchQuietDisable(); if (store != NULL) CFRelease(store); if (prefs != NULL) CFRelease(prefs); return; }
static Boolean establishNewPreferences() { CFBundleRef bundle; SCNetworkSetRef current = NULL; CFStringRef new_model; Boolean ok = FALSE; int sc_status = kSCStatusFailed; SCNetworkSetRef set = NULL; CFStringRef setName = NULL; Boolean updated = FALSE; while (TRUE) { ok = SCPreferencesLock(prefs, TRUE); if (ok) { break; } sc_status = SCError(); if (sc_status == kSCStatusStale) { SCPreferencesSynchronize(prefs); } else { SCLog(TRUE, LOG_ERR, CFSTR("Could not acquire network configuration lock: %s"), SCErrorString(sc_status)); return FALSE; } } /* Ensure that the preferences has the new 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); } current = SCNetworkSetCopyCurrent(prefs); if (current != NULL) { set = current; } if (set == NULL) { set = SCNetworkSetCreate(prefs); if (set == NULL) { ok = FALSE; sc_status = SCError(); goto done; } bundle = _SC_CFBundleGet(); if (bundle != NULL) { setName = CFBundleCopyLocalizedString(bundle, CFSTR("DEFAULT_SET_NAME"), CFSTR("Automatic"), NULL); } ok = SCNetworkSetSetName(set, (setName != NULL) ? setName : CFSTR("Automatic")); if (!ok) { sc_status = SCError(); goto done; } ok = SCNetworkSetSetCurrent(set); if (!ok) { sc_status = SCError(); goto done; } } ok = SCNetworkSetEstablishDefaultConfiguration(set); if (!ok) { sc_status = SCError(); goto done; } done : if (ok) { ok = SCPreferencesCommitChanges(prefs); if (ok) { SCLog(TRUE, LOG_NOTICE, CFSTR("New network configuration saved")); updated = TRUE; } else { sc_status = SCError(); if (sc_status == EROFS) { /* a read-only fileysstem is OK */ ok = TRUE; /* ... but we don't want to synchronize */ rofs = TRUE; } } /* apply (committed or temporary/read-only) changes */ (void) SCPreferencesApplyChanges(prefs); } else if ((current == NULL) && (set != NULL)) { (void) SCNetworkSetRemove(set); } if (!ok) { SCLog(TRUE, LOG_ERR, CFSTR("Could not establish network configuration: %s"), SCErrorString(sc_status)); } (void)SCPreferencesUnlock(prefs); if (setName != NULL) CFRelease(setName); if (set != NULL) CFRelease(set); return updated; }
Boolean _SCBondInterfaceUpdateConfiguration(SCPreferencesRef prefs) { CFArrayRef active = NULL; CFArrayRef config = NULL; CFIndex i; CFIndex nActive; CFIndex nConfig; Boolean ok = TRUE; int s = -1; if (prefs == NULL) { _SCErrorSet(kSCStatusInvalidArgument); return FALSE; } /* configured Bonds */ config = SCBondInterfaceCopyAll(prefs); nConfig = (config != NULL) ? CFArrayGetCount(config) : 0; /* active Bonds */ active = _SCBondInterfaceCopyActive(); nActive = (active != NULL) ? CFArrayGetCount(active) : 0; /* * remove any no-longer-configured bond interfaces and * any devices associated with a bond that are no longer * associated with a bond. */ for (i = 0; i < nActive; i++) { SCBondInterfaceRef a_bond; CFStringRef a_bond_if; CFIndex j; Boolean found = FALSE; a_bond = CFArrayGetValueAtIndex(active, i); a_bond_if = SCNetworkInterfaceGetBSDName(a_bond); for (j = 0; j < nConfig; j++) { SCBondInterfaceRef c_bond; CFStringRef c_bond_if; c_bond = CFArrayGetValueAtIndex(config, j); c_bond_if = SCNetworkInterfaceGetBSDName(c_bond); if (CFEqual(a_bond_if, c_bond_if)) { CFIndex a; CFArrayRef a_bond_interfaces; CFIndex a_count; CFArrayRef c_bond_interfaces; CFIndex c_count; c_bond_interfaces = SCBondInterfaceGetMemberInterfaces(c_bond); c_count = (c_bond_interfaces != NULL) ? CFArrayGetCount(c_bond_interfaces) : 0; a_bond_interfaces = SCBondInterfaceGetMemberInterfaces(a_bond); a_count = (a_bond_interfaces != NULL) ? CFArrayGetCount(a_bond_interfaces) : 0; for (a = 0; a < a_count; a++) { SCNetworkInterfaceRef a_interface; CFStringRef a_interface_if; a_interface = CFArrayGetValueAtIndex(a_bond_interfaces, a); if ((c_count == 0) || !CFArrayContainsValue(c_bond_interfaces, CFRangeMake(0, c_count), a_interface)) { /* * if this device is no longer part * of the bond. */ if (s == -1) { s = inet_dgram_socket(); if (s == -1) { _SCErrorSet(errno); ok = FALSE; goto done; } } a_interface_if = SCNetworkInterfaceGetBSDName(a_interface); if (!__bond_remove_interface(s, a_bond_if, a_interface_if)) { ok = FALSE; } } } found = TRUE; break; } } if (!found) { /* * if this interface is no longer configured */ if (s == -1) { s = inet_dgram_socket(); if (s == -1) { _SCErrorSet(errno); ok = FALSE; goto done; } } if (!__destroyInterface(s, a_bond_if)) { _SCErrorSet(errno); ok = FALSE; } } } /* * add any newly-configured bond interfaces and add any * devices that should now be associated with the bond. */ for (i = 0; i < nConfig; i++) { CFNumberRef c_bond_mode; SCBondInterfaceRef c_bond; CFArrayRef c_bond_interfaces; CFStringRef c_bond_if; CFIndex c_count; Boolean found = FALSE; CFIndex j; c_bond = CFArrayGetValueAtIndex(config, i); c_bond_if = SCNetworkInterfaceGetBSDName(c_bond); c_bond_interfaces = SCBondInterfaceGetMemberInterfaces(c_bond); c_bond_mode = SCBondInterfaceGetMode(c_bond); c_count = (c_bond_interfaces != NULL) ? CFArrayGetCount(c_bond_interfaces) : 0; for (j = 0; j < nActive; j++) { SCBondInterfaceRef a_bond; CFArrayRef a_bond_interfaces; CFNumberRef a_bond_mode; CFStringRef a_bond_if; CFIndex a_count; a_bond = CFArrayGetValueAtIndex(active, j); a_bond_if = SCNetworkInterfaceGetBSDName(a_bond); a_bond_interfaces = SCBondInterfaceGetMemberInterfaces(a_bond); a_bond_mode = SCBondInterfaceGetMode(a_bond); a_count = (a_bond_interfaces != NULL) ? CFArrayGetCount(a_bond_interfaces) : 0; if (CFEqual(c_bond_if, a_bond_if)) { CFIndex c; Boolean if_list_change = FALSE; Boolean mode_change = FALSE; found = TRUE; if (!_SC_CFEqual(a_bond_mode, c_bond_mode)) { mode_change = TRUE; } if (!_SC_CFEqual(c_bond_interfaces, a_bond_interfaces)) { if_list_change = TRUE; } if (!mode_change && !if_list_change) { break; // if no change } if (s == -1) { s = inet_dgram_socket(); if (s == -1) { _SCErrorSet(errno); ok = FALSE; goto done; } } if (mode_change) { __bond_set_mode(s, a_bond_if, c_bond_mode); } if (!if_list_change) { break; // no if list changes } /* * ensure that the first device of the bond matches, if * not then we remove all current devices and add them * back in the preferred order. */ if ((c_count > 0) && (a_count > 0) && !CFEqual(CFArrayGetValueAtIndex(c_bond_interfaces, 0), CFArrayGetValueAtIndex(a_bond_interfaces, 0))) { CFIndex a; for (a = 0; a < a_count; a++) { SCNetworkInterfaceRef a_interface; CFStringRef a_interface_if; a_interface = CFArrayGetValueAtIndex(a_bond_interfaces, a); if (!CFArrayContainsValue(c_bond_interfaces, CFRangeMake(0, c_count), a_interface)) { continue; // if already removed } a_interface_if = SCNetworkInterfaceGetBSDName(a_interface); if (!__bond_remove_interface(s, a_bond_if, a_interface_if)) { ok = FALSE; } } a_count = 0; // all active devices have been removed } /* * add any devices which are not currently associated * with the bond interface. */ for (c = 0; c < c_count; c++) { SCNetworkInterfaceRef c_interface; SCNetworkInterfacePrivateRef c_interfacePrivate; CFStringRef c_interface_if; c_interface = CFArrayGetValueAtIndex(c_bond_interfaces, c); if ((a_count == 0) || !CFArrayContainsValue(a_bond_interfaces, CFRangeMake(0, a_count), c_interface)) { /* * check if this member interface can be added to a bond. */ c_interfacePrivate = (SCNetworkInterfacePrivateRef)c_interface; if (!c_interfacePrivate->supportsBond) { // if member not supported continue; } /* * if this member interface is not currently part of the bond. */ c_interface_if = SCNetworkInterfaceGetBSDName(c_interface); if (!__bond_add_interface(s, c_bond_if, c_interface_if)) { // if member could not be added ok = FALSE; } } } break; } } if (!found) { CFIndex c; if (s == -1) { s = inet_dgram_socket(); if (s == -1) { _SCErrorSet(errno); ok = FALSE; goto done; } } /* * establish the new bond interface. */ if (!__createInterface(s, c_bond_if)) { _SCErrorSet(errno); ok = FALSE; continue; } /* set the mode */ __bond_set_mode(s, c_bond_if, c_bond_mode); /* * add the member interfaces */ for (c = 0; c < c_count; c++) { SCNetworkInterfaceRef c_interface; SCNetworkInterfacePrivateRef c_interfacePrivate; CFStringRef c_interface_if; c_interface = CFArrayGetValueAtIndex(c_bond_interfaces, c); c_interfacePrivate = (SCNetworkInterfacePrivateRef)c_interface; if (!c_interfacePrivate->supportsBond) { // if member not supported continue; } c_interface_if = SCNetworkInterfaceGetBSDName(c_interface); if (!__bond_add_interface(s, c_bond_if, c_interface_if)) { // if member could not be added ok = FALSE; } } } } done : if (active != NULL) CFRelease(active); if (config != NULL) CFRelease(config); if (s != -1) (void) close(s); return ok; }