static CFStringRef copy_primary_ip(SCDynamicStoreRef store, CFStringRef serviceID) { CFStringRef address = NULL; CFDictionaryRef dict; CFStringRef key; key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainState, serviceID, kSCEntNetIPv4); dict = SCDynamicStoreCopyValue(store, key); CFRelease(key); if (dict != NULL) { if (isA_CFDictionary(dict)) { CFArrayRef addresses; addresses = CFDictionaryGetValue(dict, kSCPropNetIPv4Addresses); if (isA_CFArray(addresses) && (CFArrayGetCount(addresses) > 0)) { address = CFArrayGetValueAtIndex(addresses, 0); if (isA_CFString(address)) { CFRetain(address); } else { address = NULL; } } } CFRelease(dict); } return address; }
void KprNetworkInterfaceSetup() { #if TARGET_OS_IPHONE struct sockaddr_in localWifiAddress; SCNetworkReachabilityContext context = {0, NULL, NULL, NULL, NULL}; SCNetworkReachabilityFlags flags; bzero(&localWifiAddress, sizeof(localWifiAddress)); localWifiAddress.sin_len = sizeof(localWifiAddress); localWifiAddress.sin_family = AF_INET; localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM); // IN_LINKLOCALNETNUM is defined in <netinet/in.h> as 169.254.0.0 gNetworkInterfaceReachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)&localWifiAddress); SCNetworkReachabilitySetCallback(gNetworkInterfaceReachability, KprNetworkInterfaceReachabilityCallback, &context); SCNetworkReachabilityScheduleWithRunLoop(gNetworkInterfaceReachability, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); SCNetworkReachabilityGetFlags(gNetworkInterfaceReachability, &flags); KprNetworkInterfaceReachabilityCallback(gNetworkInterfaceReachability, flags, NULL); #elif TARGET_OS_MAC FskErr err = kFskErrNone; SCDynamicStoreContext context = {0, NULL, NULL, NULL, NULL}; CFStringRef pattern = NULL; CFArrayRef patternList = NULL; pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv4); if (!pattern) { err = kFskErrOperationFailed; goto bail; } patternList = CFArrayCreate(NULL, (const void **)&pattern, 1, &kCFTypeArrayCallBacks); if (!patternList) { err = kFskErrOperationFailed; goto bail; } gNetworkInterfaceStore = SCDynamicStoreCreate(NULL, CFSTR("KprNetWorkInterface"), KprNetworkInterfaceStoreCallback, &context); if (!gNetworkInterfaceStore) { err = kFskErrOperationFailed; goto bail; } if (!SCDynamicStoreSetNotificationKeys(gNetworkInterfaceStore, NULL, patternList)) { err = kFskErrOperationFailed; goto bail; } gNetworkInterfaceSource = SCDynamicStoreCreateRunLoopSource(NULL, gNetworkInterfaceStore, 0); if (!gNetworkInterfaceSource) { err = kFskErrOperationFailed; goto bail; } CFRunLoopAddSource(CFRunLoopGetCurrent(), gNetworkInterfaceSource, kCFRunLoopCommonModes); KprNetworkInterfaceStoreCallback(gNetworkInterfaceStore, NULL, NULL); bail: if (err != noErr) { if (gNetworkInterfaceSource) { CFRelease(gNetworkInterfaceSource); gNetworkInterfaceSource = NULL; } if (gNetworkInterfaceStore) { CFRelease(gNetworkInterfaceStore); gNetworkInterfaceStore = NULL; } } if (patternList) CFRelease(patternList); if (pattern) CFRelease(pattern); #elif TARGET_OS_WIN32 NETIOAPI_API status = NotifyIpInterfaceChange(AF_INET, &KprNetworkInterfaceCallback, NULL, TRUE, &gNetworkInterfaceHandle); #elif TARGET_OS_KPL #ifdef KPR_CONFIG KplNetInterfaceInitialize(); KplNetInterfaceSetChangedCallback(KprNetworkInterfaceCallback, 0L); KprNetworkInterfaceCallback(0); #endif #endif }
static CFArrayRef copyCurrentDNSServers(void) { SCDynamicStoreRef store; CFPropertyListRef propList; CFStringRef scdsRegexp; CFArrayRef retval = NULL; CFStringRef serviceID; serviceID = copyCurrentPrimaryService(); if(serviceID) { scdsRegexp = SCDynamicStoreKeyCreateNetworkServiceEntity ( kCFAllocatorDefault, kSCDynamicStoreDomainState, serviceID, kSCEntNetDNS); if(scdsRegexp) { store = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("Network Diagnostics"), NULL, NULL); if(store) { propList = SCDynamicStoreCopyValue(store, scdsRegexp); if(propList) { retval = CFDictionaryGetValue(propList, CFSTR("ServerAddresses")); if (retval) { CFRetain(retval); } CFRelease(propList); } CFRelease(store); } CFRelease(scdsRegexp); } CFRelease(serviceID); } return retval; }
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; }
static CFDictionaryRef copy_app_layer_vpn_proxies(CFDictionaryRef services, CFArrayRef order, CFDictionaryRef services_info) { CFMutableDictionaryRef app_layer_proxies = NULL; CFIndex i; CFIndex n_order; if (!isA_CFDictionary(services_info)) { return NULL; } // iterate over services n_order = isA_CFArray(order) ? CFArrayGetCount(order) : 0; for (i = 0; i < n_order; i++) { CFMutableDictionaryRef newProxy; CFDictionaryRef proxy; CFDictionaryRef service; CFStringRef serviceID; CFDictionaryRef vpn; CFStringRef vpn_key; serviceID = CFArrayGetValueAtIndex(order, i); service = CFDictionaryGetValue(services, serviceID); if (!isA_CFDictionary(service)) { // if no service continue; } proxy = CFDictionaryGetValue(service, kSCEntNetProxies); if (!isA_CFDictionary(proxy)) { // if no proxy continue; } vpn_key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, serviceID, kSCEntNetVPN); vpn = CFDictionaryGetValue(services_info, vpn_key); CFRelease(vpn_key); if (!isA_CFDictionary(vpn) || !CFDictionaryContainsKey(vpn, kSCPropNetVPNAppRules)) { // if not app-layer vpn continue; } if ((app_layer_proxies != NULL) && CFDictionaryContainsKey(app_layer_proxies, serviceID)) { // if we've already processed this [app_layer_proxies] interface continue; } // add [app_layer_proxies] proxy entry newProxy = CFDictionaryCreateMutableCopy(NULL, 0, proxy); CFDictionaryRemoveValue(newProxy, kSCPropNetProxiesSupplementalMatchDomains); CFDictionaryRemoveValue(newProxy, kSCPropNetProxiesSupplementalMatchOrders); if (app_layer_proxies == NULL) { app_layer_proxies = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); } CFDictionarySetValue(app_layer_proxies, serviceID, newProxy); CFRelease(newProxy); } return app_layer_proxies; }
static OSStatus CreateIPAddressListChangeCallbackSCF(SCDynamicStoreCallBack callback, void *contextPtr, SCDynamicStoreRef *storeRef, CFRunLoopSourceRef *sourceRef) // Create a SCF dynamic store reference and a // corresponding CFRunLoop source. If you add the // run loop source to your run loop then the supplied // callback function will be called when local IP // address list changes. { OSStatus err = 0; SCDynamicStoreContext context = {0, NULL, NULL, NULL, NULL}; SCDynamicStoreRef ref; CFStringRef pattern; CFArrayRef patternList; CFRunLoopSourceRef rls; assert(callback != NULL); assert( storeRef != NULL); assert(*storeRef == NULL); assert( sourceRef != NULL); assert(*sourceRef == NULL); ref = NULL; pattern = NULL; patternList = NULL; rls = NULL; // Create a connection to the dynamic store, then create // a search pattern that finds all IPv4 entities. // The pattern is "State:/Network/Service/[^/]+/IPv4". context.info = contextPtr; ref = SCDynamicStoreCreate( NULL, CFSTR("AddIPAddressListChangeCallbackSCF"), callback, &context); //err = MoreSCError(ref); if (err == noErr) { pattern = SCDynamicStoreKeyCreateNetworkServiceEntity( NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv4); //err = MoreSCError(pattern); } // Create a pattern list containing just one pattern, // then tell SCF that we want to watch changes in keys // that match that pattern list, then create our run loop // source. if (err == noErr) { patternList = CFArrayCreate(NULL, (const void **) &pattern, 1, &kCFTypeArrayCallBacks); //err = CFQError(patternList); } if (err == noErr) { //err = MoreSCErrorBoolean( SCDynamicStoreSetNotificationKeys( ref, NULL, patternList); // ); } if (err == noErr) { rls = SCDynamicStoreCreateRunLoopSource(NULL, ref, 0); //err = MoreSCError(rls); } CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); // Clean up. //CFQRelease(pattern); //CFQRelease(patternList); if (err != noErr) { //CFQRelease(ref); ref = NULL; } *storeRef = ref; *sourceRef = rls; assert( (err == noErr) == (*storeRef != NULL) ); assert( (err == noErr) == (*sourceRef != NULL) ); return err; }
static void SetInterfaceChangedObserver_MacDesktop(OsContext* aContext, InterfaceListChanged aCallback, void* aArg) { SCDynamicStoreContext context = {0, NULL, NULL, NULL, NULL}; CFStringRef pattern = NULL; CFArrayRef patternList = NULL; CFRunLoopRef runLoop = NULL; if (NULL != aContext->iInterfaceChangedObserver) { return; } aContext->iInterfaceChangedObserver = (InterfaceChangedObserver*)malloc(sizeof(*(aContext->iInterfaceChangedObserver))); if (NULL == aContext->iInterfaceChangedObserver) { goto Error; } aContext->iInterfaceChangedObserver->iCallback = aCallback; aContext->iInterfaceChangedObserver->iArg = aArg; aContext->iInterfaceChangedObserver->iStore = NULL; aContext->iInterfaceChangedObserver->iRunLoopSource = NULL; context.info = aContext->iInterfaceChangedObserver; aContext->iInterfaceChangedObserver->iStore = SCDynamicStoreCreate(NULL, CFSTR("AddIPAddressListChangeCallbackSCF"), &InterfaceChangedDynamicStoreCallback, &context); if (NULL == aContext->iInterfaceChangedObserver->iStore) { goto Error; } pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv4); if (NULL == pattern) { goto Error; } patternList = CFArrayCreate(NULL, (const void **)&pattern, 1, &kCFTypeArrayCallBacks); if (NULL == patternList) { goto Error; } if (false == SCDynamicStoreSetNotificationKeys(aContext->iInterfaceChangedObserver->iStore, NULL, patternList)) { goto Error; } aContext->iInterfaceChangedObserver->iRunLoopSource = SCDynamicStoreCreateRunLoopSource(NULL, aContext->iInterfaceChangedObserver->iStore, 0); if (NULL == aContext->iInterfaceChangedObserver->iRunLoopSource) { goto Error; } runLoop = CFRunLoopGetMain(); if (NULL == runLoop) { goto Error; } CFRunLoopAddSource(runLoop, aContext->iInterfaceChangedObserver->iRunLoopSource, kCFRunLoopCommonModes); CFRelease(pattern); CFRelease(patternList); return; Error: if (NULL != pattern) { CFRelease(pattern); } if (NULL != patternList) { CFRelease(patternList); } if (NULL != aContext->iInterfaceChangedObserver) { if (aContext->iInterfaceChangedObserver->iStore != NULL) { CFRelease(aContext->iInterfaceChangedObserver->iStore); } if (aContext->iInterfaceChangedObserver->iRunLoopSource != NULL) { CFRelease(aContext->iInterfaceChangedObserver->iRunLoopSource); } free(aContext->iInterfaceChangedObserver); aContext->iInterfaceChangedObserver = NULL; } }
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; }
static CFArrayRef entity_all(SCDynamicStoreRef store, CFStringRef entity, CFArrayRef order) { CFMutableArrayRef defined = NULL; CFIndex i; CFIndex n; CFMutableArrayRef ordered = NULL; CFStringRef pattern; ordered = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, kSCCompAnyRegex, entity); defined = (CFMutableArrayRef)SCDynamicStoreCopyKeyList(store, pattern); CFRelease(pattern); if (defined && (CFArrayGetCount(defined) > 0)) { CFArrayRef tmp; tmp = defined; defined = CFArrayCreateMutableCopy(NULL, 0, tmp); CFRelease(tmp); } else { goto done; } n = order ? CFArrayGetCount(order) : 0; for (i = 0; i < n; i++) { CFDictionaryRef dict; CFStringRef key; CFIndex j; CFStringRef service; service = CFArrayGetValueAtIndex(order, i); if (!isA_CFString(service)) { continue; } key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, service, entity); dict = entity_one(store, key); if (dict) { CFArrayAppendValue(ordered, dict); CFRelease(dict); } j = CFArrayGetFirstIndexOfValue(defined, CFRangeMake(0, CFArrayGetCount(defined)), key); if (j != kCFNotFound) { CFArrayRemoveValueAtIndex(defined, j); } CFRelease(key); } n = CFArrayGetCount(defined); for (i = 0; i < n; i++) { CFDictionaryRef dict; CFStringRef key; key = CFArrayGetValueAtIndex(defined, i); dict = entity_one(store, key); if (dict) { CFArrayAppendValue(ordered, dict); CFRelease(dict); } } done: if (defined) CFRelease(defined); if (CFArrayGetCount(ordered) == 0) { CFRelease(ordered); ordered = NULL; } return ordered; }
static CFDictionaryRef entity_one(SCDynamicStoreRef store, CFStringRef key) { CFDictionaryRef ent_dict = NULL; CFDictionaryRef if_dict = NULL; CFStringRef if_key = NULL; CFStringRef if_port; CFMutableDictionaryRef new_dict = NULL; static CFStringRef pre = NULL; CFStringRef serviceID = NULL; CFStringRef serviceType; if (!pre) { pre = SCDynamicStoreKeyCreate(NULL, CFSTR("%@/%@/%@/"), kSCDynamicStoreDomainSetup, kSCCompNetwork, kSCCompService); } /* * get entity dictionary for service */ ent_dict = cache_SCDynamicStoreCopyValue(store, key); if (!isA_CFDictionary(ent_dict)) { goto done; } /* * get interface dictionary for service */ serviceID = parse_component(key, pre); if (!serviceID) { goto done; } if_key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, serviceID, kSCEntNetInterface); if_dict = cache_SCDynamicStoreCopyValue(store, if_key); CFRelease(if_key); if (!isA_CFDictionary(if_dict)) { goto done; } /* check the interface type */ serviceType = CFDictionaryGetValue(if_dict, kSCPropNetInterfaceType); if (!isA_CFString(serviceType) || !CFEqual(serviceType, kSCValNetInterfaceTypeEthernet)) { /* sorry, no AT networking on this interface */ goto done; } /* * get port name (from interface dictionary). */ if_port = CFDictionaryGetValue(if_dict, kSCPropNetInterfaceDeviceName); if (!isA_CFString(if_port)) { goto done; } /* * add ServiceID and interface port name to entity dictionary. */ new_dict = CFDictionaryCreateMutableCopy(NULL, 0, ent_dict); CFDictionarySetValue(new_dict, CFSTR("ServiceID"), serviceID); CFDictionarySetValue(new_dict, kSCPropNetInterfaceDeviceName, if_port); done: if (ent_dict) CFRelease(ent_dict); if (if_dict) CFRelease(if_dict); if (serviceID) CFRelease(serviceID); return (CFDictionaryRef)new_dict; }
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_show(int argc, char **argv) { SCNetworkServiceRef service = NULL; SCDynamicStoreRef store = NULL; int exit_code = 1; CFStringRef serviceID = NULL; CFStringRef iftype = NULL; CFStringRef ifsubtype = NULL; CFStringRef type_entity_key = NULL; CFStringRef subtype_entity_key = NULL; CFDictionaryRef type_entity_dict = NULL; CFDictionaryRef subtype_entity_dict = NULL; CFStringRef vpnprefpath = NULL; #if !TARGET_OS_IPHONE CFDataRef bookmarkData = NULL; CFURLRef directory = NULL; Boolean isStale = FALSE; char *path = NULL; CFIndex path_len = 0; #endif service = nc_copy_service_from_arguments(argc, argv, NULL); if (service == NULL) { SCPrint(TRUE, stderr, CFSTR("No service\n")); exit(exit_code); } serviceID = SCNetworkServiceGetServiceID(service); nc_get_service_type_and_subtype(service, &iftype, &ifsubtype); if (!CFEqual(iftype, kSCEntNetPPP) && !CFEqual(iftype, kSCEntNetIPSec) && !CFEqual(iftype, kSCEntNetVPN)) { SCPrint(TRUE, stderr, CFSTR("Not a connection oriented service: %@\n"), serviceID); goto done; } type_entity_key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, serviceID, iftype); nc_print_VPN_service(service); #if !TARGET_OS_IPHONE vpnprefpath = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@"), PREF_PREFIX, ifsubtype, PREF_SUFFIX); if (vpnprefpath == NULL) { goto skipURL; } path_len = CFStringGetLength(vpnprefpath) + 1; path = malloc(path_len); if (path == NULL) { goto skipURL; } if (!CFStringGetCString(vpnprefpath, path, path_len, kCFStringEncodingASCII)) { SCPrint(TRUE, stderr, CFSTR("CFStringGetCString failed\n")); goto done; } do_prefs_init(); /* initialization */ do_prefs_open(1, &path); /* open prefs */ bookmarkData = SCPreferencesGetValue(prefs, CFSTR("ApplicationURL")); if (bookmarkData == NULL) { goto skipURL; } directory = CFURLCreateByResolvingBookmarkData(kCFAllocatorDefault, bookmarkData, 0, NULL, NULL, &isStale, NULL); if (directory == NULL) { goto skipURL; } SCPrint(TRUE, stdout, CFSTR("ApplicationURL: %@\n"), directory); skipURL: #endif store = SCDynamicStoreCreate(NULL, CFSTR("scutil --nc"), NULL, NULL); if (store == NULL) { SCPrint(TRUE, stderr, CFSTR("Unable to create dynamic store: %s\n"), SCErrorString(SCError())); goto done; } type_entity_dict = SCDynamicStoreCopyValue(store, type_entity_key); if (!type_entity_dict) { SCPrint(TRUE, stderr, CFSTR("No \"%@\" configuration available\n"), iftype); } else { SCPrint(TRUE, stdout, CFSTR("%@ %@\n"), iftype, type_entity_dict); } if (ifsubtype) { subtype_entity_key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, serviceID, ifsubtype); subtype_entity_dict = SCDynamicStoreCopyValue(store, subtype_entity_key); if (!subtype_entity_dict) { // } else { SCPrint(TRUE, stdout, CFSTR("%@ %@\n"), ifsubtype, subtype_entity_dict); } } exit_code = 0; done: my_CFRelease(&type_entity_key); my_CFRelease(&type_entity_dict); my_CFRelease(&subtype_entity_key); my_CFRelease(&subtype_entity_dict); my_CFRelease(&store); my_CFRelease(&service); my_CFRelease(&vpnprefpath); _prefs_close(); exit(exit_code); }
int checkVPNInterfaceOrServiceBlocked (const char *location, char *interface_buf) { // check to see if interface is captive: if so, bail if the interface is not ready. if (check_interface_captive_and_not_ready(gDynamicStore, interface_buf)) { // TODO: perhaps we should wait for a few seconds? return true; } // return 1, if this is a delete event, and; // TODO: add support for IPv6 <rdar://problem/5920237> // walk Setup:/Network/Service/* and check if there are service entries referencing this interface. e.g. Setup:/Network/Service/44DB8790-0177-4F17-8D4E-37F9413D1D87/Interface:DeviceName == interface, other_serv_found = 1 // Setup:/Network/Interface/"interface"/AirPort:'PowerEnable' == 0 || Setup:/Network/Interface/"interface"/IPv4 is missing, interf_down = 1 if (gDynamicStore) { CFStringRef interf_key; CFMutableArrayRef interf_keys; CFStringRef pattern; CFMutableArrayRef patterns; CFDictionaryRef dict = NULL; CFIndex i; const void * keys_q[128]; const void ** keys = keys_q; const void * values_q[128]; const void ** values = values_q; CFIndex n; CFStringRef vpn_if; int other_serv_found = 0, interf_down = 0; vpn_if = CFStringCreateWithCStringNoCopy(NULL, interface_buf, kCFStringEncodingASCII, kCFAllocatorNull); if (!vpn_if) { // if we could not initialize interface CFString syslog(LOG_NOTICE, "%s: failed to initialize interface CFString", location); goto done; } interf_keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); // get Setup:/Network/Interface/<vpn_if>/Airport interf_key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainSetup, vpn_if, kSCEntNetAirPort); CFArrayAppendValue(interf_keys, interf_key); CFRelease(interf_key); // get State:/Network/Interface/<vpn_if>/Airport interf_key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, vpn_if, kSCEntNetAirPort); CFArrayAppendValue(interf_keys, interf_key); CFRelease(interf_key); // get Setup:/Network/Service/*/Interface pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, kSCCompAnyRegex, kSCEntNetInterface); CFArrayAppendValue(patterns, pattern); CFRelease(pattern); // get Setup:/Network/Service/*/IPv4 pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, kSCCompAnyRegex, kSCEntNetIPv4); CFArrayAppendValue(patterns, pattern); CFRelease(pattern); dict = SCDynamicStoreCopyMultiple(gDynamicStore, interf_keys, patterns); CFRelease(interf_keys); CFRelease(patterns); if (!dict) { // if we could not access the SCDynamicStore syslog(LOG_NOTICE, "%s: failed to initialize SCDynamicStore dictionary", location); CFRelease(vpn_if); goto done; } // look for the service which matches the provided prefixes n = CFDictionaryGetCount(dict); if (n <= 0) { syslog(LOG_NOTICE, "%s: empty SCDynamicStore dictionary", location); CFRelease(vpn_if); goto done; } if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) { keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0); values = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0); } CFDictionaryGetKeysAndValues(dict, keys, values); for (i=0; i < n; i++) { CFStringRef s_key = (CFStringRef)keys[i]; CFDictionaryRef s_dict = (CFDictionaryRef)values[i]; CFStringRef s_if; if (!isA_CFString(s_key) || !isA_CFDictionary(s_dict)) { continue; } if (CFStringHasSuffix(s_key, kSCEntNetInterface)) { // is a Service Interface entity s_if = CFDictionaryGetValue(s_dict, kSCPropNetInterfaceDeviceName); if (isA_CFString(s_if) && CFEqual(vpn_if, s_if)) { CFArrayRef components; CFStringRef serviceIDRef = NULL, serviceKey = NULL; other_serv_found = 1; // extract service ID components = CFStringCreateArrayBySeparatingStrings(NULL, s_key, CFSTR("/")); if (CFArrayGetCount(components) > 3) { serviceIDRef = CFArrayGetValueAtIndex(components, 3); //if (new key) Setup:/Network/Service/service_id/IPv4 is missing, then interf_down = 1 serviceKey = SCDynamicStoreKeyCreateNetworkServiceEntity(0, kSCDynamicStoreDomainSetup, serviceIDRef, kSCEntNetIPv4); if (!serviceKey || !CFDictionaryGetValue(dict, serviceKey)) { syslog(LOG_NOTICE, "%s: detected disabled IPv4 Config", location); interf_down = 1; } if (serviceKey) CFRelease(serviceKey); } if (components) CFRelease(components); if (interf_down) break; } continue; } else if (CFStringHasSuffix(s_key, kSCEntNetAirPort)) { // Interface/<vpn_if>/Airport entity if (CFStringHasPrefix(s_key, kSCDynamicStoreDomainSetup)) { CFBooleanRef powerEnable = CFDictionaryGetValue(s_dict, kSCPropNetAirPortPowerEnabled); if (isA_CFBoolean(powerEnable) && CFEqual(powerEnable, kCFBooleanFalse)) { syslog(LOG_NOTICE, "%s: detected AirPort, PowerEnable == FALSE", location); interf_down = 1; break; } } else if (CFStringHasPrefix(s_key, kSCDynamicStoreDomainState)) { UInt16 temp; CFNumberRef airStatus = CFDictionaryGetValue(s_dict, CFSTR("Power Status")); if (isA_CFNumber(airStatus) && CFNumberGetValue(airStatus, kCFNumberShortType, &temp)) { if (temp ==0) { syslog(LOG_NOTICE, "%s: detected AirPort, PowerStatus == 0", location); } } } continue; } } if (vpn_if) CFRelease(vpn_if); if (keys != keys_q) { CFAllocatorDeallocate(NULL, keys); CFAllocatorDeallocate(NULL, values); } done : if (dict) CFRelease(dict); return (other_serv_found == 0 || interf_down == 1); } return 0; }