/* * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * The contents of this file constitute Original Code as defined in and * are subject to the Apple Public Source License Version 1.1 (the * "License"). You may not use this file except in compliance with the * License. Please obtain a copy of the License at * http://www.apple.com/publicsource and read it before using this file. * * This Original Code and all software distributed under the License are * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* * Modification History * * April 29, 2002 Allan Nathanson * - add global state information (primary service, interface) * * June 24, 2001 Allan Nathanson * - update to public SystemConfiguration.framework APIs * * July 7, 2000 Allan Nathanson * - initial revision */ #include #include #include #include #include #include #include #include #include #include #include #include #include "cfManager.h" #define HOSTCONFIG "/etc/hostconfig" SCDynamicStoreRef store = NULL; CFRunLoopSourceRef rls = NULL; CFMutableDictionaryRef oldGlobals = NULL; CFMutableArrayRef oldConfigFile = NULL; CFMutableDictionaryRef oldDefaults = NULL; CFMutableDictionaryRef oldStartup = NULL; Boolean _verbose = FALSE; static void updateDefaults(const void *key, const void *val, void *context) { CFStringRef ifName = (CFStringRef)key; CFDictionaryRef oldDict; CFDictionaryRef newDict = (CFDictionaryRef)val; CFNumberRef defaultNode; CFNumberRef defaultNetwork; CFStringRef defaultZone; if (!CFDictionaryGetValueIfPresent(oldDefaults, ifName, (const void **)&oldDict) || !CFEqual(oldDict, newDict)) { char ifr_name[IFNAMSIZ]; bzero(&ifr_name, sizeof(ifr_name)); if (!CFStringGetCString(ifName, ifr_name, sizeof(ifr_name), kCFStringEncodingMacRoman)) { SCLog(TRUE, LOG_ERR, CFSTR("CFStringGetCString: could not convert interface name to C string")); return; } /* * Set preferred Network and Node ID */ if (CFDictionaryGetValueIfPresent(newDict, kSCPropNetAppleTalkNetworkID, (const void **)&defaultNetwork) && CFDictionaryGetValueIfPresent(newDict, kSCPropNetAppleTalkNodeID, (const void **)&defaultNode) ) { struct at_addr init_address; int status; /* * set the default node and network */ CFNumberGetValue(defaultNetwork, kCFNumberShortType, &init_address.s_net); CFNumberGetValue(defaultNode, kCFNumberCharType, &init_address.s_node); status = at_setdefaultaddr(ifr_name, &init_address); if (status == -1) { SCLog(TRUE, LOG_ERR, CFSTR("at_setdefaultaddr() failed")); } } /* * Set default zone */ if (CFDictionaryGetValueIfPresent(newDict, kSCPropNetAppleTalkDefaultZone, (const void **)&defaultZone) ) { at_nvestr_t zone; /* * set the "default zone" for this interface */ bzero(&zone, sizeof(zone)); if (CFStringGetCString(defaultZone, zone.str, sizeof(zone.str), kCFStringEncodingMacRoman)) { int status; zone.len = strlen(zone.str); status = at_setdefaultzone(ifr_name, &zone); if (status == -1) { SCLog(TRUE, LOG_ERR, CFSTR("at_setdefaultzone() failed")); } } else { SCLog(TRUE, LOG_ERR, CFSTR("CFStringGetCString: could not convert default zone to C string")); } } } return; } static void addZoneToPorts(const void *key, const void *val, void *context) { CFStringRef zone = (CFStringRef)key; CFArrayRef ifArray = (CFArrayRef)val; CFMutableArrayRef zones = (CFMutableArrayRef)context; CFStringRef ifList; CFStringRef configInfo; ifList = CFStringCreateByCombiningStrings(NULL, ifArray, CFSTR(":")); configInfo = CFStringCreateWithFormat(NULL, NULL, CFSTR(":%@:%@"), zone, ifList); CFArrayAppendValue(zones, configInfo); CFRelease(configInfo); CFRelease(ifList); return; } /* * Function: parse_component * Purpose: * Given a string 'key' and a string prefix 'prefix', * return the next component in the slash '/' separated * key. * * Examples: * 1. key = "a/b/c" prefix = "a/" * returns "b" * 2. key = "a/b/c" prefix = "a/b/" * returns "c" */ static CFStringRef parse_component(CFStringRef key, CFStringRef prefix) { CFMutableStringRef comp; CFRange range; if (CFStringHasPrefix(key, prefix) == FALSE) { return NULL; } comp = CFStringCreateMutableCopy(NULL, 0, key); CFStringDelete(comp, CFRangeMake(0, CFStringGetLength(prefix))); range = CFStringFind(comp, CFSTR("/"), 0); if (range.location == kCFNotFound) { return comp; } range.length = CFStringGetLength(comp) - range.location; CFStringDelete(comp, range); return comp; } 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 = 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 = 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; } static CFArrayRef entity_all(SCDynamicStoreRef store, CFStringRef entity, CFArrayRef order) { CFMutableArrayRef defined = NULL; int i; 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; } for (i = 0; order && i < CFArrayGetCount(order); 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 >= 0) { CFArrayRemoveValueAtIndex(defined, j); } CFRelease(key); } for (i = 0; i < CFArrayGetCount(defined); 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 CFStringRef encodeName(CFStringRef name, CFStringEncoding encoding) { CFDataRef bytes; CFMutableStringRef encodedName = NULL; CFIndex len; if (!isA_CFString(name)) { return NULL; } if (encoding == kCFStringEncodingASCII) { return CFRetain(name); } /* * encode the potentially non-printable string */ bytes = CFStringCreateExternalRepresentation(NULL, name, encoding, 0); if (bytes) { unsigned char *byte; CFIndex i; /* * check if the MacRoman string can be represented as ASCII */ if (encoding == kCFStringEncodingMacRoman) { CFDataRef ascii; ascii = CFStringCreateExternalRepresentation(NULL, name, kCFStringEncodingASCII, 0); if (ascii) { CFRelease(ascii); CFRelease(bytes); return CFRetain(name); } } encodedName = CFStringCreateMutable(NULL, 0); len = CFDataGetLength(bytes); byte = (unsigned char *)CFDataGetBytePtr(bytes); for (i=0; i 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 1) ? TRUE : FALSE; load(CFBundleGetMainBundle(), (argc > 1) ? TRUE : FALSE); CFRunLoopRun(); /* not reached */ exit(0); return 0; } #endif