/* * Copyright (c) 2000 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@ */ #include #include #include #include #include #include #include #include #include #define SYSTEMCONFIGURATION_NEW_API #include #include "cfManager.h" #define HOSTCONFIG "/etc/hostconfig" SCDSessionRef session = NULL; CFMutableDictionaryRef oldGlobals = NULL; CFMutableArrayRef oldConfigFile = NULL; CFMutableDictionaryRef oldDefaults = NULL; static __inline__ CFTypeRef isA_CFType(CFTypeRef obj, CFTypeID type) { if (obj == NULL) return (NULL); if (CFGetTypeID(obj) != type) return (NULL); return (obj); } static __inline__ CFTypeRef isA_CFDictionary(CFTypeRef obj) { return (isA_CFType(obj, CFDictionaryGetTypeID())); } static __inline__ CFTypeRef isA_CFArray(CFTypeRef obj) { return (isA_CFType(obj, CFArrayGetTypeID())); } static __inline__ CFTypeRef isA_CFString(CFTypeRef obj) { return (isA_CFType(obj, CFStringGetTypeID())); } 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, (void **)&oldDict) || !CFEqual(oldDict, newDict)) { char ifr_name[IFNAMSIZ]; bzero(&ifr_name, sizeof(ifr_name)); if (!CFStringGetCString(ifName, ifr_name, sizeof(ifr_name), kCFStringEncodingMacRoman)) { SCDLog(LOG_ERR, CFSTR("CFStringGetCString: could not convert interface name to C string")); return; } /* * Set preferred Network and Node ID */ if (CFDictionaryGetValueIfPresent(newDict, kSCPropNetAppleTalkNetworkID, (void **)&defaultNetwork) && CFDictionaryGetValueIfPresent(newDict, kSCPropNetAppleTalkNodeID, (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) { SCDLog(LOG_ERR, CFSTR("at_setdefaultaddr() failed")); } } /* * Set default zone */ if (CFDictionaryGetValueIfPresent(newDict, kSCPropNetAppleTalkDefaultZone, (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) { SCDLog(LOG_ERR, CFSTR("at_setdefaultzone() failed")); } } else { SCDLog(LOG_ERR, CFSTR("CFStringGetCString: could not convert default zone to C string")); } } } return; } 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(SCDSessionRef session, CFStringRef key) { CFDictionaryRef ent_dict = NULL; SCDHandleRef ent_handle = NULL; CFDictionaryRef if_dict = NULL; SCDHandleRef if_handle = NULL; CFStringRef if_key = NULL; CFStringRef if_port; CFMutableDictionaryRef new_dict = NULL; static CFStringRef pre = NULL; CFStringRef serviceID = NULL; CFStringRef serviceType; SCDStatus status; if (pre == NULL) { pre = SCDKeyCreate(CFSTR("%@/%@/%@/"), kSCCacheDomainSetup, kSCCompNetwork, kSCCompService); } /* * get entity dictionary for service */ status = SCDGet(session, key, &ent_handle); if (status != SCD_OK) { goto done; } ent_dict = isA_CFDictionary(SCDHandleGetData(ent_handle)); if (ent_dict == NULL) { goto done; } /* * get interface dictionary for service */ serviceID = parse_component(key, pre); if (serviceID == NULL) { goto done; } if_key = SCDKeyCreateNetworkServiceEntity(kSCCacheDomainSetup, serviceID, kSCEntNetInterface); CFRelease(serviceID); status = SCDGet(session, if_key, &if_handle); CFRelease(if_key); if (status != SCD_OK) { goto done; } if_dict = isA_CFDictionary(SCDHandleGetData(if_handle)); if (if_dict == NULL) { goto done; } /* check the interface type */ if (!CFDictionaryGetValueIfPresent(if_dict, kSCPropNetInterfaceType, (void **)&serviceType) || !CFEqual(serviceType, kSCValNetInterfaceTypeEthernet)) { /* sorry, no AT networking on this interface */ goto done; } /* * add port name (from interface dictionary) to entity * dictionary and return the result. */ if_port = CFDictionaryGetValue(if_dict, kSCPropNetInterfaceDeviceName); if (if_port == NULL) { goto done; } new_dict = CFDictionaryCreateMutableCopy(NULL, 0, ent_dict); CFDictionarySetValue(new_dict, kSCPropNetInterfaceDeviceName, if_port); done: if (ent_handle) SCDHandleRelease(ent_handle); if (if_handle) SCDHandleRelease(if_handle); return (CFDictionaryRef)new_dict; } static CFArrayRef entity_all(SCDSessionRef session, CFStringRef entity, CFArrayRef order) { CFMutableArrayRef defined = NULL; int i; CFStringRef key; CFMutableArrayRef ordered = NULL; SCDStatus status; ordered = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); key = SCDKeyCreateNetworkServiceEntity(kSCCacheDomainSetup, kSCCompAnyRegex, entity); status = SCDList(session, key, kSCDRegexKey, &defined); CFRelease(key); if (status != SCD_OK) { goto done; } if (CFArrayGetCount(defined) > 0) { CFMutableArrayRef 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; key = SCDKeyCreateNetworkServiceEntity(kSCCacheDomainSetup, CFArrayGetValueAtIndex(order, i), entity); dict = entity_one(session, 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(session, 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 (name == NULL) { return NULL; } if (encoding == kCFStringEncodingMacRoman) { return CFRetain(name); } /* * encode the potentially non-printable string */ bytes = CFStringCreateExternalRepresentation(NULL, name, encoding, 0); if (bytes) { unsigned char *byte; CFIndex i; encodedName = CFStringCreateMutable(NULL, 0); len = CFDataGetLength(bytes); byte = (unsigned char *)CFDataGetBytePtr(bytes); for (i=0; i 1) { CFNumberGetValue(CFArrayGetValueAtIndex(networkRange, 1), kCFNumberIntType, &eNetwork); } else { eNetwork = sNetwork; } CFStringAppendFormat(portConfig, NULL, CFSTR("%d:%d:"), sNetwork, eNetwork); /* * establish the zones associated with this port */ for (j=0; j