NetworkStateNotifier::NetworkStateNotifier() : m_isOnLine(false) , m_networkStateChangeTimer(*this, &NetworkStateNotifier::networkStateChangeTimerFired) { SCDynamicStoreContext context = { 0, this, 0, 0, 0 }; m_store = adoptCF(SCDynamicStoreCreate(0, CFSTR("com.apple.WebCore"), dynamicStoreCallback, &context)); if (!m_store) return; RetainPtr<CFRunLoopSourceRef> configSource = adoptCF(SCDynamicStoreCreateRunLoopSource(0, m_store.get(), 0)); if (!configSource) return; CFRunLoopAddSource(CFRunLoopGetMain(), configSource.get(), kCFRunLoopCommonModes); RetainPtr<CFMutableArrayRef> keys = adoptCF(CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks)); RetainPtr<CFMutableArrayRef> patterns = adoptCF(CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks)); RetainPtr<CFStringRef> key; RetainPtr<CFStringRef> pattern; key = adoptCF(SCDynamicStoreKeyCreateNetworkGlobalEntity(0, kSCDynamicStoreDomainState, kSCEntNetIPv4)); CFArrayAppendValue(keys.get(), key.get()); pattern = adoptCF(SCDynamicStoreKeyCreateNetworkInterfaceEntity(0, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv4)); CFArrayAppendValue(patterns.get(), pattern.get()); key = adoptCF(SCDynamicStoreKeyCreateNetworkGlobalEntity(0, kSCDynamicStoreDomainState, kSCEntNetDNS)); CFArrayAppendValue(keys.get(), key.get()); SCDynamicStoreSetNotificationKeys(m_store.get(), keys.get(), patterns.get()); updateState(); }
static CFDictionaryRef smb_copy_global_configuration(SCDynamicStoreRef store) { CFDictionaryRef dict; CFStringRef key; key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetSMB); dict = SCDynamicStoreCopyValue(store, key); CFRelease(key); if (dict != NULL) { if (isA_CFDictionary(dict)) { return dict; } CFRelease(dict); } dict = CFDictionaryCreate(NULL, // allocator NULL, // keys NULL, // values 0, // numValues &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); return dict; }
static CFStringRef copy_primary_service(SCDynamicStoreRef store) { CFDictionaryRef dict; CFStringRef key; CFStringRef serviceID = NULL; key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4); dict = SCDynamicStoreCopyValue(store, key); CFRelease(key); if (dict != NULL) { if (isA_CFDictionary(dict)) { serviceID = CFDictionaryGetValue(dict, kSCDynamicStorePropNetPrimaryService); if (isA_CFString(serviceID)) { CFRetain(serviceID); } else { serviceID = NULL; } } CFRelease(dict); } return serviceID; }
static char * getVPNInterfaceBuf (struct service *serv) { char *interface_buf; SCLog(TRUE, LOG_INFO, CFSTR("%s:"), __FUNCTION__); switch (serv->type) { case TYPE_IPSEC: interface_buf = serv->u.ipsec.lower_interface; break; case TYPE_PPP: if (!serv->u.ppp.lower_interface[0]) { CFStringRef string, key; CFDictionaryRef dict; SCLog(TRUE, LOG_INFO, CFSTR("%s: lower_interface is null"), __FUNCTION__); /* TODO: this part should be change to grab the real lower interface instead of the primary */ key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4); if (key) { dict = SCDynamicStoreCopyValue(gDynamicStore, key); CFRelease(key); if (dict) { if ((string = CFDictionaryGetValue(dict, kSCDynamicStorePropNetPrimaryInterface))) { CFStringGetCString(string, serv->u.ppp.lower_interface, sizeof(serv->u.ppp.lower_interface), kCFStringEncodingASCII); SCLog(TRUE, LOG_INFO, CFSTR("%s: lower_interface is gotten %@"), __FUNCTION__, string); } CFRelease(dict); } } } interface_buf = serv->u.ppp.lower_interface; SCLog(TRUE, LOG_INFO, CFSTR("%s: lower_interface is %s"), __FUNCTION__, interface_buf[0]? interface_buf : "null"); break; default: interface_buf = NULL; break; } return interface_buf; }
int main(int argc, char **argv) { CFDictionaryRef entities; CFStringRef key; CFDictionaryRef newProxy = NULL; CFStringRef pattern; CFMutableArrayRef patterns; CFStringRef primary = NULL; CFMutableDictionaryRef primary_proxy = NULL; CFArrayRef service_order = NULL; CFMutableDictionaryRef service_state_dict; CFDictionaryRef setup_global_ipv4; CFDictionaryRef state_global_ipv4; SCDynamicStoreRef store; _sc_log = FALSE; _sc_verbose = (argc > 1) ? TRUE : FALSE; store = SCDynamicStoreCreate(NULL, CFSTR("TEST"), NULL, NULL); // get IPv4, IPv6, and Proxies entities patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv4); CFArrayAppendValue(patterns, pattern); CFRelease(pattern); pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv6); CFArrayAppendValue(patterns, pattern); CFRelease(pattern); pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, kSCCompAnyRegex, kSCEntNetProxies); CFArrayAppendValue(patterns, pattern); CFRelease(pattern); pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetProxies); CFArrayAppendValue(patterns, pattern); CFRelease(pattern); entities = SCDynamicStoreCopyMultiple(store, NULL, patterns); CFRelease(patterns); service_state_dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionaryApplyFunction(entities, split, service_state_dict); CFRelease(entities); // get primary service ID key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4); state_global_ipv4 = SCDynamicStoreCopyValue(store, key); CFRelease(key); if (state_global_ipv4 != NULL) { primary = CFDictionaryGetValue(state_global_ipv4, kSCDynamicStorePropNetPrimaryService); if (primary != NULL) { CFDictionaryRef service_dict; // get proxy configuration for primary service service_dict = CFDictionaryGetValue(service_state_dict, primary); if (service_dict != NULL) { CFDictionaryRef service_proxy; service_proxy = CFDictionaryGetValue(service_dict, kSCEntNetProxies); if (service_proxy != NULL) { primary_proxy = CFDictionaryCreateMutableCopy(NULL, 0, service_proxy); CFDictionaryRemoveValue(primary_proxy, kSCPropInterfaceName); } } } } // get serviceOrder key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainSetup, kSCEntNetIPv4); setup_global_ipv4 = SCDynamicStoreCopyValue(store, key); CFRelease(key); if (setup_global_ipv4 != NULL) { service_order = CFDictionaryGetValue(setup_global_ipv4, kSCPropNetServiceOrder); } // update proxy configuration proxy_configuration_init(CFBundleGetMainBundle()); newProxy = proxy_configuration_update(primary_proxy, service_state_dict, service_order, NULL); if (newProxy != NULL) { SCPrint(TRUE, stdout, CFSTR("%@\n"), newProxy); CFRelease(newProxy); } // cleanup if (setup_global_ipv4 != NULL) CFRelease(setup_global_ipv4); if (state_global_ipv4 != NULL) CFRelease(state_global_ipv4); CFRelease(service_state_dict); CFRelease(store); /* not reached */ exit(0); return 0; }
__private_extern__ void load_smb_configuration(Boolean verbose) { CFStringRef key; CFMutableArrayRef keys = NULL; dispatch_block_t notify_block; Boolean ok; CFMutableArrayRef patterns = NULL; uint32_t status; /* initialize a few globals */ store = SCDynamicStoreCreate(NULL, CFSTR("smb-configuration"), configuration_changed, NULL); if (store == NULL) { my_log(LOG_ERR, "SCDynamicStoreCreate() failed: %s", SCErrorString(SCError())); goto error; } /* establish notification keys and patterns */ keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); /* ...watch for SMB configuration changes */ key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetSMB); CFArrayAppendValue(keys, key); CFRelease(key); /* ...watch for ComputerName changes */ key = SCDynamicStoreKeyCreateComputerName(NULL); CFArrayAppendValue(keys, key); CFRelease(key); /* ...watch for local (multicast DNS) hostname changes */ key = SCDynamicStoreKeyCreateHostNames(NULL); CFArrayAppendValue(keys, key); CFRelease(key); /* register the keys/patterns */ ok = SCDynamicStoreSetNotificationKeys(store, keys, patterns); CFRelease(keys); CFRelease(patterns); if (!ok) { my_log(LOG_ERR, "SCDynamicStoreSetNotificationKeys() failed: %s", SCErrorString(SCError())); goto error; } rl = CFRunLoopGetCurrent(); rls = SCDynamicStoreCreateRunLoopSource(NULL, store, 0); if (rls == NULL) { my_log(LOG_ERR, "SCDynamicStoreCreateRunLoopSource() failed: %s", SCErrorString(SCError())); goto error; } CFRunLoopAddSource(rl, rls, kCFRunLoopDefaultMode); /* ...watch for primary service/interface and DNS configuration changes */ notify_block = ^{ CFArrayRef changes; CFStringRef key; key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetDNS); changes = CFArrayCreate(NULL, (const void **)&key, 1, &kCFTypeArrayCallBacks); (*configuration_changed)(store, changes, NULL); CFRelease(changes); CFRelease(key); return; }; status = notify_register_dispatch(_SC_NOTIFY_NETWORK_CHANGE, ¬ify_token, dispatch_get_main_queue(), ^(int token){ CFRunLoopPerformBlock(rl, kCFRunLoopDefaultMode, notify_block); CFRunLoopWakeUp(rl); });
static void * /* O - Return status/value */ sysEventThreadEntry(void) { io_object_t powerNotifierObj; /* Power notifier object */ IONotificationPortRef powerNotifierPort; /* Power notifier port */ SCDynamicStoreRef store = NULL;/* System Config dynamic store */ CFRunLoopSourceRef powerRLS = NULL,/* Power runloop source */ storeRLS = NULL;/* System Config runloop source */ CFStringRef key[6], /* System Config keys */ pattern[2]; /* System Config patterns */ CFArrayRef keys = NULL, /* System Config key array*/ patterns = NULL;/* System Config pattern array */ SCDynamicStoreContext storeContext; /* Dynamic store context */ CFRunLoopTimerContext timerContext; /* Timer context */ cupsd_thread_data_t threadData; /* Thread context data for the * * runloop notifiers */ /* * Register for power state change notifications */ bzero(&threadData, sizeof(threadData)); threadData.sysevent.powerKernelPort = IORegisterForSystemPower(&threadData, &powerNotifierPort, sysEventPowerNotifier, &powerNotifierObj); if (threadData.sysevent.powerKernelPort) { powerRLS = IONotificationPortGetRunLoopSource(powerNotifierPort); CFRunLoopAddSource(CFRunLoopGetCurrent(), powerRLS, kCFRunLoopDefaultMode); } else DEBUG_puts("sysEventThreadEntry: error registering for system power " "notifications"); /* * Register for system configuration change notifications */ bzero(&storeContext, sizeof(storeContext)); storeContext.info = &threadData; store = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("cupsd"), sysEventConfigurationNotifier, &storeContext); if (!ComputerNameKey) ComputerNameKey = SCDynamicStoreKeyCreateComputerName(kCFAllocatorDefault); if (!BTMMKey) BTMMKey = SCDynamicStoreKeyCreate(kCFAllocatorDefault, CFSTR("Setup:/Network/BackToMyMac")); if (!NetworkGlobalKeyIPv4) NetworkGlobalKeyIPv4 = SCDynamicStoreKeyCreateNetworkGlobalEntity(kCFAllocatorDefault, kSCDynamicStoreDomainState, kSCEntNetIPv4); if (!NetworkGlobalKeyIPv6) NetworkGlobalKeyIPv6 = SCDynamicStoreKeyCreateNetworkGlobalEntity(kCFAllocatorDefault, kSCDynamicStoreDomainState, kSCEntNetIPv6); if (!NetworkGlobalKeyDNS) NetworkGlobalKeyDNS = SCDynamicStoreKeyCreateNetworkGlobalEntity(kCFAllocatorDefault, kSCDynamicStoreDomainState, kSCEntNetDNS); if (!HostNamesKey) HostNamesKey = SCDynamicStoreKeyCreateHostNames(kCFAllocatorDefault); if (!NetworkInterfaceKeyIPv4) NetworkInterfaceKeyIPv4 = SCDynamicStoreKeyCreateNetworkInterfaceEntity(kCFAllocatorDefault, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv4); if (!NetworkInterfaceKeyIPv6) NetworkInterfaceKeyIPv6 = SCDynamicStoreKeyCreateNetworkInterfaceEntity(kCFAllocatorDefault, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv6); if (store && ComputerNameKey && HostNamesKey && NetworkGlobalKeyIPv4 && NetworkGlobalKeyIPv6 && NetworkGlobalKeyDNS && NetworkInterfaceKeyIPv4 && NetworkInterfaceKeyIPv6) { key[0] = ComputerNameKey; key[1] = BTMMKey; key[2] = NetworkGlobalKeyIPv4; key[3] = NetworkGlobalKeyIPv6; key[4] = NetworkGlobalKeyDNS; key[5] = HostNamesKey; pattern[0] = NetworkInterfaceKeyIPv4; pattern[1] = NetworkInterfaceKeyIPv6; keys = CFArrayCreate(kCFAllocatorDefault, (const void **)key, sizeof(key) / sizeof(key[0]), &kCFTypeArrayCallBacks); patterns = CFArrayCreate(kCFAllocatorDefault, (const void **)pattern, sizeof(pattern) / sizeof(pattern[0]), &kCFTypeArrayCallBacks); if (keys && patterns && SCDynamicStoreSetNotificationKeys(store, keys, patterns)) { if ((storeRLS = SCDynamicStoreCreateRunLoopSource(kCFAllocatorDefault, store, 0)) != NULL) { CFRunLoopAddSource(CFRunLoopGetCurrent(), storeRLS, kCFRunLoopDefaultMode); } else DEBUG_printf(("sysEventThreadEntry: SCDynamicStoreCreateRunLoopSource " "failed: %s\n", SCErrorString(SCError()))); } else DEBUG_printf(("sysEventThreadEntry: SCDynamicStoreSetNotificationKeys " "failed: %s\n", SCErrorString(SCError()))); } else DEBUG_printf(("sysEventThreadEntry: SCDynamicStoreCreate failed: %s\n", SCErrorString(SCError()))); if (keys) CFRelease(keys); if (patterns) CFRelease(patterns); /* * Set up a timer to delay the wake change notifications. * * The initial time is set a decade or so into the future, we'll adjust * this later. */ bzero(&timerContext, sizeof(timerContext)); timerContext.info = &threadData; threadData.timerRef = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + (86400L * 365L * 10L), 86400L * 365L * 10L, 0, 0, sysEventTimerNotifier, &timerContext); CFRunLoopAddTimer(CFRunLoopGetCurrent(), threadData.timerRef, kCFRunLoopDefaultMode); /* * Store our runloop in a global so the main thread can use it to stop us. */ pthread_mutex_lock(&SysEventThreadMutex); SysEventRunloop = CFRunLoopGetCurrent(); pthread_cond_signal(&SysEventThreadCond); pthread_mutex_unlock(&SysEventThreadMutex); /* * Disappear into the runloop until it's stopped by the main thread. */ CFRunLoopRun(); /* * Clean up before exiting. */ if (threadData.timerRef) { CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), threadData.timerRef, kCFRunLoopDefaultMode); CFRelease(threadData.timerRef); } if (threadData.sysevent.powerKernelPort) { CFRunLoopRemoveSource(CFRunLoopGetCurrent(), powerRLS, kCFRunLoopDefaultMode); IODeregisterForSystemPower(&powerNotifierObj); IOServiceClose(threadData.sysevent.powerKernelPort); IONotificationPortDestroy(powerNotifierPort); } if (storeRLS) { CFRunLoopRemoveSource(CFRunLoopGetCurrent(), storeRLS, kCFRunLoopDefaultMode); CFRunLoopSourceInvalidate(storeRLS); CFRelease(storeRLS); } if (store) CFRelease(store); pthread_exit(NULL); }
CFNetDiagnosticStatus CFNetDiagnosticCopyNetworkStatusPassively(CFNetDiagnosticRef details, CFStringRef *description) { CFMutableDictionaryRef detailsDict = (CFMutableDictionaryRef)details; CFNetDiagnosticStatus retval = kCFNetDiagnosticConnectionIndeterminate; CFStringRef serviceID; SCDynamicStoreRef store; store = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("CFNetDiagnostics"), NULL, NULL); if(store) { serviceID = CFDictionaryGetValue(detailsDict, _CFNetDiagnosticServiceIDKey); if(serviceID) { //If there is a specific ServiceID we only scan on it. We can only get in this position through SPIs retval = _CFNetDiagnosticCopyNetworkStatusPassivelyInterfaceSpecific(store, serviceID, description); } else { //Iterate through all serviceIDs. If any are good, then we return it CFStringRef pattern = NULL; CFDictionaryRef dict = NULL; CFArrayRef serviceOrder = NULL; CFIndex i, count; CFNetDiagnosticStatus serviceState = kCFNetDiagnosticConnectionDown; pattern = SCDynamicStoreKeyCreateNetworkGlobalEntity( NULL, (CFStringRef) kSCDynamicStoreDomainSetup, (CFStringRef) kSCEntNetIPv4 ); if(pattern) { dict = SCDynamicStoreCopyValue( store, pattern ); CFRelease( pattern ); } if(dict) { serviceOrder = CFDictionaryGetValue(dict, CFSTR("ServiceOrder")); CFRetain(serviceOrder); CFRelease(dict); } if(serviceOrder) { count = CFArrayGetCount(serviceOrder); retval = kCFNetDiagnosticConnectionDown; for ( i = 0; i < count; i++ ) { serviceID = CFArrayGetValueAtIndex(serviceOrder, i); serviceState = _CFNetDiagnosticCopyNetworkStatusPassivelyInterfaceSpecific(store, serviceID, description); if(serviceState == kCFNetDiagnosticConnectionDown) { retval = kCFNetDiagnosticConnectionDown; if (description) { *description = CFCopyLocalizedStringFromTableInBundle( CFSTR("CONNECTION_DOWN"), NULL, CFBundleGetBundleWithIdentifier(CFSTR("com.apple.CFNetwork")), "This computer's Internet connect appears to be offline."); } } else if (serviceState == kCFNetDiagnosticConnectionIndeterminate) { retval = kCFNetDiagnosticConnectionIndeterminate; if (description) { *description = CFCopyLocalizedStringFromTableInBundle( CFSTR("CONNECTION_INDETERMINATE"), NULL, CFBundleGetBundleWithIdentifier(CFSTR("com.apple.CFNetwork")), "This computer's Internet may be offline."); } } else if (serviceState == kCFNetDiagnosticConnectionUp) { retval = kCFNetDiagnosticConnectionUp; if (description) { *description = CFCopyLocalizedStringFromTableInBundle( CFSTR("CONNECTION_UP"), NULL, CFBundleGetBundleWithIdentifier(CFSTR("com.apple.CFNetwork")), "This computer's Internet may be online."); } break; } else { //FIXME //NOT REACHED log an error } } CFRelease(serviceOrder); } } CFRelease(store); } return retval; }
static boolean_t updateConfiguration(int *newState) { boolean_t changed = FALSE; CFStringRef computerName; CFStringEncoding computerNameEncoding; CFArrayRef configuredServices = NULL; CFDictionaryRef dict; CFIndex i; CFIndex ifCount = 0; CFMutableArrayRef info = NULL; CFArrayRef interfaces = NULL; CFStringRef key; CFArrayRef keys; CFIndex n; CFMutableArrayRef newConfigFile; CFMutableDictionaryRef newDefaults; CFMutableDictionaryRef newDict; CFMutableDictionaryRef newGlobals; CFMutableDictionaryRef newGlobalsX; /* newGlobals without ServiceID */ CFMutableDictionaryRef newStartup; CFMutableDictionaryRef newZones; CFNumberRef num; CFMutableDictionaryRef curGlobalsX; /* curGlobals without ServiceID */ CFStringRef pattern; boolean_t postGlobals = FALSE; CFStringRef primaryPort = NULL; /* primary interface */ CFStringRef primaryZone = NULL; CFArrayRef serviceOrder = NULL; CFDictionaryRef setGlobals = NULL; cache_open(); /* * establish the "new" AppleTalk configuration */ *newState = curState; newConfigFile = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); newGlobals = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); newDefaults = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); newStartup = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); newZones = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); /* initialize overall state */ CFDictionarySetValue(newStartup, CFSTR("APPLETALK"), CFSTR("-NO-")); /* * get the global settings (ServiceOrder, ComputerName, ...) */ key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainSetup, kSCEntNetAppleTalk); setGlobals = cache_SCDynamicStoreCopyValue(store, key); CFRelease(key); if (setGlobals) { if (isA_CFDictionary(setGlobals)) { /* get service order */ serviceOrder = CFDictionaryGetValue(setGlobals, kSCPropNetServiceOrder); serviceOrder = isA_CFArray(serviceOrder); if (serviceOrder) { CFRetain(serviceOrder); } } else { CFRelease(setGlobals); setGlobals = NULL; } } /* * if we don't have an AppleTalk ServiceOrder, use IPv4's (if defined) */ if (!serviceOrder) { key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainSetup, kSCEntNetIPv4); dict = cache_SCDynamicStoreCopyValue(store, key); CFRelease(key); if (dict) { if (isA_CFDictionary(dict)) { serviceOrder = CFDictionaryGetValue(dict, kSCPropNetServiceOrder); serviceOrder = isA_CFArray(serviceOrder); if (serviceOrder) { CFRetain(serviceOrder); } } CFRelease(dict); } } /* * get the list of ALL configured services */ configuredServices = entity_all(store, kSCEntNetAppleTalk, serviceOrder); if (configuredServices) { ifCount = CFArrayGetCount(configuredServices); } if (serviceOrder) CFRelease(serviceOrder); /* * get the list of ALL active interfaces */ key = SCDynamicStoreKeyCreateNetworkInterface(NULL, kSCDynamicStoreDomainState); dict = cache_SCDynamicStoreCopyValue(store, key); CFRelease(key); if (dict) { if (isA_CFDictionary(dict)) { interfaces = CFDictionaryGetValue(dict, kSCDynamicStorePropNetInterfaces); interfaces = isA_CFArray(interfaces); if (interfaces) { CFRetain(interfaces); } } CFRelease(dict); } /* * get the list of previously configured services */ pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetAppleTalk); keys = SCDynamicStoreCopyKeyList(store, pattern); CFRelease(pattern); if (keys) { info = CFArrayCreateMutableCopy(NULL, 0, keys); CFRelease(keys); } /* * iterate over each configured service to establish the new * configuration. */ for (i = 0; i < ifCount; i++) { CFDictionaryRef service; CFStringRef ifName; CFStringRef configMethod; CFMutableStringRef portConfig = NULL; CFArrayRef networkRange; /* for seed ports, CFArray[2] of CFNumber (lo, hi) */ int sNetwork; int eNetwork; CFArrayRef zoneList; /* for seed ports, CFArray[] of CFString (zones names) */ CFIndex zCount; CFIndex j; CFMutableDictionaryRef ifDefaults = NULL; CFNumberRef defaultNetwork; CFNumberRef defaultNode; CFStringRef defaultZone; /* get AppleTalk service dictionary */ service = CFArrayGetValueAtIndex(configuredServices, i); /* get interface name */ ifName = CFDictionaryGetValue(service, kSCPropNetInterfaceDeviceName); /* check inteface availability */ if (!interfaces || !CFArrayContainsValue(interfaces, CFRangeMake(0, CFArrayGetCount(interfaces)), ifName)) { /* if interface not available */ goto nextIF; } /* check interface link status */ key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, ifName, kSCEntNetLink); dict = cache_SCDynamicStoreCopyValue(store, key); CFRelease(key); if (dict) { Boolean linkStatus = TRUE; /* assume the link is "up" */ Boolean ifDetaching = FALSE; /* assume link is not detaching */ /* the link key for this interface is available */ if (isA_CFDictionary(dict)) { CFBooleanRef bVal; bVal = CFDictionaryGetValue(dict, kSCPropNetLinkActive); if (isA_CFBoolean(bVal)) { linkStatus = CFBooleanGetValue(bVal); } /* check if interface is detaching - value doesn't really matter, only that it exists */ ifDetaching = CFDictionaryContainsKey(dict, kSCPropNetLinkDetaching); } CFRelease(dict); if (!linkStatus || ifDetaching) { /* if link status down or the interface is detaching */ goto nextIF; } } /* * Determine configuration method for this service */ configMethod = CFDictionaryGetValue(service, kSCPropNetAppleTalkConfigMethod); if (!isA_CFString(configMethod)) { /* if no ConfigMethod */ goto nextIF; } if (!CFEqual(configMethod, kSCValNetAppleTalkConfigMethodNode ) && !CFEqual(configMethod, kSCValNetAppleTalkConfigMethodRouter ) && !CFEqual(configMethod, kSCValNetAppleTalkConfigMethodSeedRouter)) { /* if not one of the expected values, disable */ SCLog(TRUE, LOG_NOTICE, CFSTR("Unexpected AppleTalk ConfigMethod: %@"), configMethod); goto nextIF; } /* * the first service to be defined will always be "primary" */ if (CFArrayGetCount(newConfigFile) == 0) { CFDictionaryRef active; CFDictionarySetValue(newGlobals, kSCDynamicStorePropNetPrimaryService, CFDictionaryGetValue(service, CFSTR("ServiceID"))); CFDictionarySetValue(newGlobals, kSCDynamicStorePropNetPrimaryInterface, ifName); /* and check if AT newtorking is active on the primary interface */ key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, ifName, kSCEntNetAppleTalk); active = cache_SCDynamicStoreCopyValue(store, key); CFRelease(key); if (active) { if (isA_CFDictionary(active)) { postGlobals = TRUE; } CFRelease(active); } } /* * define the port */ portConfig = CFStringCreateMutable(NULL, 0); CFStringAppendFormat(portConfig, NULL, CFSTR("%@:"), ifName); if (CFEqual(configMethod, kSCValNetAppleTalkConfigMethodSeedRouter)) { CFNumberRef num; /* * we have been asked to configure this interface as a * seed port. Ensure that we have been provided at least * one network number, have been provided with at least * one zonename, ... */ networkRange = CFDictionaryGetValue(service, kSCPropNetAppleTalkSeedNetworkRange); if (!isA_CFArray(networkRange) || (CFArrayGetCount(networkRange) == 0)) { SCLog(TRUE, LOG_NOTICE, CFSTR("AppleTalk configuration error (%@)"), kSCPropNetAppleTalkSeedNetworkRange); goto nextIF; } /* * establish the starting and ending network numbers */ num = CFArrayGetValueAtIndex(networkRange, 0); if (!isA_CFNumber(num)) { SCLog(TRUE, LOG_NOTICE, CFSTR("AppleTalk configuration error (%@)"), kSCPropNetAppleTalkSeedNetworkRange); goto nextIF; } CFNumberGetValue(num, kCFNumberIntType, &sNetwork); eNetwork = sNetwork; if (CFArrayGetCount(networkRange) > 1) { num = CFArrayGetValueAtIndex(networkRange, 1); if (!isA_CFNumber(num)) { SCLog(TRUE, LOG_NOTICE, CFSTR("AppleTalk configuration error (%@)"), kSCPropNetAppleTalkSeedNetworkRange); goto nextIF; } CFNumberGetValue(num, kCFNumberIntType, &eNetwork); } CFStringAppendFormat(portConfig, NULL, CFSTR("%d:%d:"), sNetwork, eNetwork); /* * establish the zones associated with this port */ zoneList = CFDictionaryGetValue(service, kSCPropNetAppleTalkSeedZones); if (!isA_CFArray(zoneList)) { SCLog(TRUE, LOG_NOTICE, CFSTR("AppleTalk configuration error (%@)"), kSCPropNetAppleTalkSeedZones); goto nextIF; } zCount = CFArrayGetCount(zoneList); for (j = 0; j < zCount; j++) { CFStringRef zone; CFArrayRef ifList; CFMutableArrayRef newIFList; zone = CFArrayGetValueAtIndex(zoneList, j); if (!isA_CFString(zone)) { continue; } if (CFDictionaryGetValueIfPresent(newZones, zone, (const void **)&ifList)) { /* known zone */ newIFList = CFArrayCreateMutableCopy(NULL, 0, ifList); } else { /* new zone */ newIFList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); } CFArrayAppendValue(newIFList, ifName); CFArraySortValues(newIFList, CFRangeMake(0, CFArrayGetCount(newIFList)), (CFComparatorFunction)CFStringCompare, NULL); CFDictionarySetValue(newZones, zone, newIFList); CFRelease(newIFList); /* * flag the default zone */ if (!primaryZone) { primaryZone = CFRetain(zone); } } if (!primaryZone) { SCLog(TRUE, LOG_NOTICE, CFSTR("AppleTalk configuration error (%@)"), kSCPropNetAppleTalkSeedZones); goto nextIF; } } /* get the (per-interface) "Computer Name" */ computerName = CFDictionaryGetValue(service, kSCPropNetAppleTalkComputerName); if (CFDictionaryGetValueIfPresent(service, kSCPropNetAppleTalkComputerNameEncoding, (const void **)&num) && isA_CFNumber(num)) { CFNumberGetValue(num, kCFNumberIntType, &computerNameEncoding); } else { computerNameEncoding = CFStringGetSystemEncoding(); } encodeName(computerName, computerNameEncoding, newStartup, newGlobals); /* * declare the first configured AppleTalk service / interface * as the "home port". */ if (CFArrayGetCount(newConfigFile) == 0) { CFStringAppend(portConfig, CFSTR("*")); primaryPort = CFRetain(ifName); } CFArrayAppendValue(newConfigFile, portConfig); /* * get the per-interface defaults */ ifDefaults = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); defaultNetwork = CFDictionaryGetValue(service, kSCPropNetAppleTalkNetworkID); defaultNode = CFDictionaryGetValue(service, kSCPropNetAppleTalkNodeID); if (isA_CFNumber(defaultNetwork) && isA_CFNumber(defaultNode)) { /* * set the default node and network */ CFDictionarySetValue(ifDefaults, kSCPropNetAppleTalkNetworkID, defaultNetwork); CFDictionarySetValue(ifDefaults, kSCPropNetAppleTalkNodeID, defaultNode); } if ((CFDictionaryGetValueIfPresent(service, kSCPropNetAppleTalkDefaultZone, (const void **)&defaultZone) == TRUE)) { /* * set the default zone for this interface */ CFDictionarySetValue(ifDefaults, kSCPropNetAppleTalkDefaultZone, defaultZone); } CFDictionarySetValue(newDefaults, ifName, ifDefaults); CFRelease(ifDefaults); switch (CFArrayGetCount(newConfigFile)) { case 1: /* * first AppleTalk interface */ CFDictionarySetValue(newStartup, CFSTR("APPLETALK"), ifName); break; case 2: /* second AppleTalk interface */ if (!CFEqual(CFDictionaryGetValue(newStartup, CFSTR("APPLETALK")), CFSTR("-ROUTER-"))) { /* * if not routing (yet), configure as multi-home */ CFDictionarySetValue(newStartup, CFSTR("APPLETALK"), CFSTR("-MULTIHOME-")); } break; } if (CFEqual(configMethod, kSCValNetAppleTalkConfigMethodRouter) || CFEqual(configMethod, kSCValNetAppleTalkConfigMethodSeedRouter)) { /* if not a simple node, enable routing */ CFDictionarySetValue(newStartup, CFSTR("APPLETALK"), CFSTR("-ROUTER-")); } /* * establish the State:/Network/Service/nnn/AppleTalk key info */ key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainState, CFDictionaryGetValue(service, CFSTR("ServiceID")), kSCEntNetAppleTalk); newDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionaryAddValue(newDict, kSCPropInterfaceName, ifName); cache_SCDynamicStoreSetValue(store, key, newDict); CFRelease(newDict); if (info) { j = CFArrayGetFirstIndexOfValue(info, CFRangeMake(0, CFArrayGetCount(info)), key); if (j != kCFNotFound) { CFArrayRemoveValueAtIndex(info, j); } } CFRelease(key); nextIF : if (portConfig) CFRelease(portConfig); } if (primaryZone) { CFArrayRef ifList; CFMutableArrayRef newIFList; ifList = CFDictionaryGetValue(newZones, primaryZone); if (CFArrayContainsValue(ifList, CFRangeMake(0, CFArrayGetCount(ifList)), primaryPort)) { newIFList = CFArrayCreateMutableCopy(NULL, 0, ifList); CFArrayAppendValue(newIFList, CFSTR("*")); CFDictionarySetValue(newZones, primaryZone, newIFList); CFRelease(newIFList); } CFRelease(primaryZone); } if (primaryPort) { CFRelease(primaryPort); } /* sort the ports */ i = CFArrayGetCount(newConfigFile); CFArraySortValues(newConfigFile, CFRangeMake(0, i), (CFComparatorFunction)CFStringCompare, NULL); /* add the zones to the configuration */ CFDictionaryApplyFunction(newZones, addZoneToPorts, newConfigFile); CFRelease(newZones); /* sort the zones */ CFArraySortValues(newConfigFile, CFRangeMake(i, CFArrayGetCount(newConfigFile)-i), (CFComparatorFunction)CFStringCompare, NULL); /* ensure that the last line of the configuration file is terminated */ CFArrayAppendValue(newConfigFile, CFSTR("")); /* * Check if we have a "ComputerName" and look elsewhere if we don't have * one yet. */ if (!CFDictionaryContainsKey(newStartup, CFSTR("APPLETALK_HOSTNAME")) && (setGlobals != NULL)) { computerName = CFDictionaryGetValue(setGlobals, kSCPropNetAppleTalkComputerName); if (CFDictionaryGetValueIfPresent(setGlobals, kSCPropNetAppleTalkComputerNameEncoding, (const void **)&num) && isA_CFNumber(num)) { CFNumberGetValue(num, kCFNumberIntType, &computerNameEncoding); } else { computerNameEncoding = CFStringGetSystemEncoding(); } encodeName(computerName, computerNameEncoding, newStartup, newGlobals); } if (!CFDictionaryContainsKey(newStartup, CFSTR("APPLETALK_HOSTNAME"))) { computerName = SCDynamicStoreCopyComputerName(store, &computerNameEncoding); if (computerName) { encodeName(computerName, computerNameEncoding, newStartup, newGlobals); CFRelease(computerName); } } if (!CFDictionaryContainsKey(newStartup, CFSTR("APPLETALK_HOSTNAME"))) { struct utsname name; if (uname(&name) == 0) { computerName = CFStringCreateWithCString(NULL, name.nodename, kCFStringEncodingASCII); if (computerName) { encodeName(computerName, kCFStringEncodingASCII, NULL, newGlobals); CFRelease(computerName); } } } /* compare the previous and current configurations */ curGlobalsX = CFDictionaryCreateMutableCopy(NULL, 0, curGlobals); CFDictionaryRemoveValue(curGlobalsX, kSCDynamicStorePropNetPrimaryService); newGlobalsX = CFDictionaryCreateMutableCopy(NULL, 0, newGlobals); CFDictionaryRemoveValue(newGlobalsX, kSCDynamicStorePropNetPrimaryService); key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetAppleTalk); if (CFEqual(curGlobalsX , newGlobalsX ) && CFEqual(curConfigFile , newConfigFile) && CFEqual(curDefaults , newDefaults ) && CFEqual(curStartup , newStartup ) ) { /* * the configuration has not changed. */ if (postGlobals) { /* * the requested configuration hasn't changed but we * now need to tell everyone that AppleTalk is active. */ if (!SCDynamicStoreSetValue(store, key, newGlobals)) { SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreSetValue() failed: %s"), SCErrorString(SCError())); } } CFRelease(newGlobals); CFRelease(newConfigFile); CFRelease(newDefaults); CFRelease(newStartup); } else if (CFArrayGetCount(newConfigFile) <= 1) { /* * the configuration has changed but there are no * longer any interfaces configured for AppleTalk * networking. */ /* * remove the global (State:/Network/Global/AppleTalk) key. * * Note: it will be restored later after AT networking has * been activated. */ /* remove the (/etc/appletalk.cfg) configuration file */ (void)unlink(AT_CFG_FILE); /* * update the per-service (and global) state */ cache_SCDynamicStoreRemoveValue(store, key); // remove State:/Network/Global/AppleTalk n = CFArrayGetCount(info); for (i = 0; i < n; i++) { CFStringRef xKey = CFArrayGetValueAtIndex(info, i); cache_SCDynamicStoreRemoveValue(store, xKey); } cache_write(store); /* flag this as a new configuration */ *newState = -(abs(curState) + 1); changed = TRUE; } else { /* * the configuration has changed. */ /* update the (/etc/appletalk.cfg) configuration file */ configWrite(AT_CFG_FILE, newConfigFile); /* * update the per-service (and global) state * * Note: if present, we remove any existing global state key and allow it * to be restored after the stack has been re-started. */ CFDictionaryApplyFunction(newDefaults, updateDefaults, NULL); cache_SCDynamicStoreRemoveValue(store, key); // remove State:/Network/Global/AppleTalk n = CFArrayGetCount(info); for (i = 0; i < n; i++) { CFStringRef xKey = CFArrayGetValueAtIndex(info, i); cache_SCDynamicStoreRemoveValue(store, xKey); } cache_write(store); /* flag this as a new configuration */ *newState = abs(curState) + 1; changed = TRUE; } CFRelease(curGlobalsX); CFRelease(newGlobalsX); CFRelease(key); if (changed) { CFRelease(curGlobals); curGlobals = newGlobals; CFRelease(curConfigFile); curConfigFile = newConfigFile; CFRelease(curDefaults); curDefaults = newDefaults; CFRelease(curStartup); curStartup = newStartup; } if (info) CFRelease(info); if (interfaces) CFRelease(interfaces); if (configuredServices) CFRelease(configuredServices); if (setGlobals) CFRelease(setGlobals); cache_close(); return changed; }
void load(CFBundleRef bundle, Boolean bundleVerbose) { CFStringRef key; CFMutableArrayRef keys = NULL; CFStringRef pattern; CFMutableArrayRef patterns = NULL; CFRunLoopSourceRef rls; if (bundleVerbose) { _verbose = TRUE; } SCLog(_verbose, LOG_DEBUG, CFSTR("load() called")); SCLog(_verbose, LOG_DEBUG, CFSTR(" bundle ID = %@"), CFBundleGetIdentifier(bundle)); /* initialize a few globals */ curGlobals = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); curConfigFile = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); curDefaults = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); curStartup = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); /* open a "configd" store to allow cache updates */ store = SCDynamicStoreCreate(NULL, CFSTR("AppleTalk Configuraton plug-in"), atConfigChangedCallback, NULL); if (!store) { SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreCreate() failed: %s"), SCErrorString(SCError())); goto error; } /* establish notificaiton keys and patterns */ keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); /* ...watch for (global) AppleTalk configuration changes */ key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainSetup, kSCEntNetAppleTalk); CFArrayAppendValue(keys, key); CFRelease(key); /* ...watch for (per-service) AppleTalk configuration changes */ pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, kSCCompAnyRegex, kSCEntNetAppleTalk); CFArrayAppendValue(patterns, pattern); CFRelease(pattern); /* ...watch for network interface link status changes */ pattern = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetLink); CFArrayAppendValue(patterns, pattern); CFRelease(pattern); /* ...watch for (per-interface) AppleTalk configuration changes */ pattern = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetAppleTalk); CFArrayAppendValue(patterns, pattern); CFRelease(pattern); /* ...watch for computer name changes */ key = SCDynamicStoreKeyCreateComputerName(NULL); CFArrayAppendValue(keys, key); CFRelease(key); /* register the keys/patterns */ if (!SCDynamicStoreSetNotificationKeys(store, keys, patterns)) { SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreSetNotificationKeys() failed: %s"), SCErrorString(SCError())); goto error; } rls = SCDynamicStoreCreateRunLoopSource(NULL, store, 0); if (!rls) { SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreCreateRunLoopSource() failed: %s"), SCErrorString(SCError())); goto error; } CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); CFRelease(rls); CFRelease(keys); CFRelease(patterns); return; error : if (curGlobals) CFRelease(curGlobals); if (curConfigFile) CFRelease(curConfigFile); if (curDefaults) CFRelease(curDefaults); if (curStartup) CFRelease(curStartup); if (store) CFRelease(store); if (keys) CFRelease(keys); if (patterns) CFRelease(patterns); return; }
static void nc_ondemand(int argc, char **argv) { int exit_code = 1; CFStringRef key = NULL; CFDictionaryRef ondemand_dict = NULL; SCDynamicStoreRef store; store = SCDynamicStoreCreate(NULL, CFSTR("scutil --nc"), nc_ondemand_callback, NULL); if (store == NULL) { SCPrint(TRUE, stderr, CFSTR("Unable to create dynamic store: %s\n"), SCErrorString(SCError())); goto done; } if (argc == 1) { #if !TARGET_IPHONE_SIMULATOR if (strcmp("--refresh", argv[0]) == 0) { SCNetworkConnectionRef connection = NULL; connection = SCNetworkConnectionCreate(kCFAllocatorDefault, NULL, NULL); if (connection && SCNetworkConnectionRefreshOnDemandState(connection)) { exit_code = 0; } if (exit_code) { SCPrint(TRUE, stderr, CFSTR("Unable to refresh OnDemand state: %s\n"), SCErrorString(SCError())); } my_CFRelease(&connection); goto done; } #endif // !TARGET_IPHONE_SIMULATOR ondemand_nodename = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8); } else if (argc != 0) { SCPrint(TRUE, stderr, CFSTR("Usage: scutil --nc ondemand [-W] [hostname]\n" " scutil --nc ondemand -- --refresh\n")); goto done; } key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetOnDemand); if (ondemand_nodename) { checkOnDemandHost(store, ondemand_nodename, FALSE); checkOnDemandHost(store, ondemand_nodename, TRUE); } else { ondemand_dict = SCDynamicStoreCopyValue(store, key); if (ondemand_dict) { SCPrint(TRUE, stdout, CFSTR("%@ %@\n"), kSCEntNetOnDemand, ondemand_dict); } else { SCPrint(TRUE, stdout, CFSTR("%@ not configured\n"), kSCEntNetOnDemand); } } if (ondemandwatch) { CFMutableArrayRef keys = NULL; keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); CFArrayAppendValue(keys, key); SCDynamicStoreSetNotificationKeys(store, keys, NULL); my_CFRelease(&keys); SCDynamicStoreSetDispatchQueue(store, dispatch_get_main_queue()); CFRunLoopRun(); } exit_code = 0; done: my_CFRelease(&ondemand_dict); my_CFRelease(&key); my_CFRelease(&store); my_CFRelease(&ondemand_nodename); exit(exit_code); }
/* This code adapted from "Living in a Dynamic TCP/IP Environment" technote. */ static Boolean install_ipaddr_source (void) { CFRunLoopSourceRef source = NULL; SCDynamicStoreContext context = {0}; SCDynamicStoreRef ref; ref = SCDynamicStoreCreate (NULL, CFSTR ("AddIPAddressListChangeCallbackSCF"), ipaddr_callback, &context); if (ref != NULL) { const void *keys[4], *patterns[2]; int i; keys[0] = SCDynamicStoreKeyCreateNetworkGlobalEntity (NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4); keys[1] = SCDynamicStoreKeyCreateNetworkGlobalEntity (NULL, kSCDynamicStoreDomainState, kSCEntNetIPv6); keys[2] = SCDynamicStoreKeyCreateComputerName (NULL); keys[3] = SCDynamicStoreKeyCreateHostNames (NULL); patterns[0] = SCDynamicStoreKeyCreateNetworkInterfaceEntity (NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv4); patterns[1] = SCDynamicStoreKeyCreateNetworkInterfaceEntity (NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv6); if (keys[0] != NULL && keys[1] != NULL && keys[2] != NULL && keys[3] != NULL && patterns[0] != NULL && patterns[1] != NULL) { CFArrayRef key_array, pattern_array; key_array = CFArrayCreate (NULL, keys, 4, &kCFTypeArrayCallBacks); pattern_array = CFArrayCreate (NULL, patterns, 2, &kCFTypeArrayCallBacks); if (key_array != NULL || pattern_array != NULL) { SCDynamicStoreSetNotificationKeys (ref, key_array, pattern_array); source = SCDynamicStoreCreateRunLoopSource (NULL, ref, 0); } if (key_array != NULL) CFRelease (key_array); if (pattern_array != NULL) CFRelease (pattern_array); } for (i = 0; i < 4; i++) if (keys[i] != NULL) CFRelease (keys[i]); for (i = 0; i < 2; i++) if (patterns[i] != NULL) CFRelease (patterns[i]); CFRelease (ref); } if (source != NULL) { CFRunLoopAddSource (CFRunLoopGetCurrent (), source, kCFRunLoopDefaultMode); CFRelease (source); } return source != NULL; }