X-Git-Url: https://git.saurik.com/apple/configd.git/blobdiff_plain/4c5e92e2493bdfbbce40e998f3b607c72c47af2c..dbf6a266c384fc8b55e00a396eebe5cb62e21547:/Plugins/KernelEventMonitor/ev_appletalk.c?ds=sidebyside diff --git a/Plugins/KernelEventMonitor/ev_appletalk.c b/Plugins/KernelEventMonitor/ev_appletalk.c new file mode 100644 index 0000000..cbcfd2e --- /dev/null +++ b/Plugins/KernelEventMonitor/ev_appletalk.c @@ -0,0 +1,400 @@ +/* + * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * Modification History + * + * August 5, 2002 Allan Nathanson + * - split code out from eventmon.c + */ + +#include "eventmon.h" +#include "cache.h" +#include "ev_appletalk.h" + +// from +#define DDP_MIN_NETWORK 0x0001 +#define DDP_MAX_NETWORK 0xfffe + + +static int +get_atalk_interface_cfg(const char *if_name, at_if_cfg_t *cfg) +{ + int fd; + + /* open socket */ + if ((fd = socket(AF_APPLETALK, SOCK_RAW, 0)) < 0) + return -1; + + /* get config info for given interface */ + strncpy(cfg->ifr_name, if_name, sizeof(cfg->ifr_name)); + if (ioctl(fd, AIOCGETIFCFG, (caddr_t)cfg) < 0) { + (void)close(fd); + return -1; + } + + (void)close(fd); + return 0; +} + + +static CFMutableDictionaryRef +getIF(CFStringRef key, CFMutableDictionaryRef oldIFs, CFMutableDictionaryRef newIFs) +{ + CFDictionaryRef dict = NULL; + CFMutableDictionaryRef newDict = NULL; + + if (CFDictionaryGetValueIfPresent(newIFs, key, (const void **)&dict)) { + newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict); + } else { + dict = cache_SCDynamicStoreCopyValue(store, key); + if (dict) { + CFDictionarySetValue(oldIFs, key, dict); + if (isA_CFDictionary(dict)) { + newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict); + CFDictionaryRemoveValue(newDict, kSCPropNetAppleTalkNetworkID); + CFDictionaryRemoveValue(newDict, kSCPropNetAppleTalkNodeID); + CFDictionaryRemoveValue(newDict, kSCPropNetAppleTalkNetworkRange); + CFDictionaryRemoveValue(newDict, kSCPropNetAppleTalkDefaultZone); + } + CFRelease(dict); + } + } + + if (!newDict) { + newDict = CFDictionaryCreateMutable(NULL, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + } + + return newDict; +} + + +static void +updateStore(const void *key, const void *value, void *context) +{ + CFDictionaryRef dict; + CFDictionaryRef newDict = (CFDictionaryRef)value; + CFDictionaryRef oldIFs = (CFDictionaryRef)context; + + dict = CFDictionaryGetValue(oldIFs, key); + + if (!dict || !CFEqual(dict, newDict)) { + if (CFDictionaryGetCount(newDict) > 0) { + cache_SCDynamicStoreSetValue(store, key, newDict); + } else if (dict) { + cache_SCDynamicStoreRemoveValue(store, key); + } + } + + return; +} + + +__private_extern__ +void +interface_update_appletalk(struct ifaddrs *ifap, const char *if_name) +{ + struct ifaddrs *ifa; + struct ifaddrs *ifap_temp = NULL; + CFStringRef interface; + boolean_t interfaceFound = FALSE; + CFStringRef key = NULL; + CFMutableDictionaryRef oldIFs; + CFMutableDictionaryRef newDict = NULL; + CFMutableDictionaryRef newIFs; + + oldIFs = CFDictionaryCreateMutable(NULL, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + newIFs = CFDictionaryCreateMutable(NULL, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + if (!ifap) { + if (getifaddrs(&ifap_temp) < 0) { + SCLog(TRUE, LOG_ERR, CFSTR("getifaddrs() failed: %s"), strerror(errno)); + goto error; + } + ifap = ifap_temp; + } + + for (ifa = ifap; ifa; ifa = ifa->ifa_next) { + at_if_cfg_t cfg; + int iVal; + CFNumberRef num; + struct sockaddr_at *sat; + + if (ifa->ifa_addr->sa_family != AF_APPLETALK) { + continue; /* sorry, not interested */ + } + + /* check if this is the requested interface */ + if (if_name) { + if (strncmp(if_name, ifa->ifa_name, IFNAMSIZ) == 0) { + interfaceFound = TRUE; /* yes, this is the one I want */ + } else { + continue; /* sorry, not interested */ + } + } + + /* get the current cache information */ + interface = CFStringCreateWithCString(NULL, ifa->ifa_name, kCFStringEncodingMacRoman); + key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, + kSCDynamicStoreDomainState, + interface, + kSCEntNetAppleTalk); + CFRelease(interface); + + newDict = getIF(key, oldIFs, newIFs); + + sat = (struct sockaddr_at *)ifa->ifa_addr; + + iVal = (int)sat->sat_addr.s_net; + num = CFNumberCreate(NULL, kCFNumberIntType, &iVal); + CFDictionarySetValue(newDict, kSCPropNetAppleTalkNetworkID, num); + CFRelease(num); + + iVal = (int)sat->sat_addr.s_node; + num = CFNumberCreate(NULL, kCFNumberIntType, &iVal); + CFDictionarySetValue(newDict, kSCPropNetAppleTalkNodeID, num); + CFRelease(num); + + if (get_atalk_interface_cfg(ifa->ifa_name, &cfg) == 0) { + CFStringRef zone; + + /* + * Set starting and ending net values + */ + if (!(((cfg.netStart == 0) && (cfg.netEnd == 0)) || + ((cfg.netStart == DDP_MIN_NETWORK) && (cfg.netEnd == DDP_MAX_NETWORK)))) { + CFMutableArrayRef array; + + array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + + iVal = cfg.netStart; + num = CFNumberCreate(NULL, kCFNumberIntType, &iVal); + CFArrayAppendValue(array, num); + CFRelease(num); + + iVal = cfg.netEnd; + num = CFNumberCreate(NULL, kCFNumberIntType, &iVal); + CFArrayAppendValue(array, num); + CFRelease(num); + + CFDictionarySetValue(newDict, kSCPropNetAppleTalkNetworkRange, array); + CFRelease(array); + } + + /* + * Set the default zone + */ + zone = CFStringCreateWithPascalString(NULL, + (ConstStr255Param)&cfg.zonename, + kCFStringEncodingMacRoman); + CFDictionarySetValue(newDict, kSCPropNetAppleTalkDefaultZone, zone); + CFRelease(zone); + } + + CFDictionarySetValue(newIFs, key, newDict); + CFRelease(newDict); + CFRelease(key); + } + + /* if the last address[es] were removed from the target interface */ + if (if_name && !interfaceFound) { + interface = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingMacRoman); + key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, + kSCDynamicStoreDomainState, + interface, + kSCEntNetAppleTalk); + CFRelease(interface); + + newDict = getIF(key, oldIFs, newIFs); + + CFDictionarySetValue(newIFs, key, newDict); + CFRelease(newDict); + CFRelease(key); + } + + CFDictionaryApplyFunction(newIFs, updateStore, oldIFs); + + error : + + if (ifap_temp) freeifaddrs(ifap_temp); + CFRelease(oldIFs); + CFRelease(newIFs); + + return; +} + + +__private_extern__ +void +interface_update_atalk_address(struct kev_atalk_data *aEvent, const char *if_name) +{ + CFStringRef interface; + CFStringRef key; + CFDictionaryRef dict; + CFMutableDictionaryRef newDict = NULL; + CFNumberRef newNode, newNet; + int node; + int net; + + /* get the current cache information */ + interface = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingMacRoman); + key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, + kSCDynamicStoreDomainState, + interface, + kSCEntNetAppleTalk); + CFRelease(interface); + + dict = cache_SCDynamicStoreCopyValue(store, key); + if (dict) { + if (isA_CFDictionary(dict)) { + newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict); + } + CFRelease(dict); + } + + if (!newDict) { + newDict = CFDictionaryCreateMutable(NULL, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + } + + /* Update node/net values in cache */ + node = (int)aEvent->node_data.address.s_node; + net = (int)aEvent->node_data.address.s_net; + + newNode = CFNumberCreate(NULL, kCFNumberIntType, &node); + newNet = CFNumberCreate(NULL, kCFNumberIntType, &net); + + CFDictionarySetValue(newDict, kSCPropNetAppleTalkNodeID, newNode); + CFDictionarySetValue(newDict, kSCPropNetAppleTalkNetworkID, newNet); + + CFRelease(newNode); + CFRelease(newNet); + + /* update cache */ + cache_SCDynamicStoreSetValue(store, key, newDict); + CFRelease(newDict); + CFRelease(key); + return; +} + + +__private_extern__ +void +interface_update_atalk_zone(struct kev_atalk_data *aEvent, const char *if_name) +{ + CFStringRef interface; + CFStringRef key; + CFDictionaryRef dict; + CFMutableDictionaryRef newDict = NULL; + CFStringRef newZone; + + /* get the current cache information */ + interface = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingMacRoman); + key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, + kSCDynamicStoreDomainState, + interface, + kSCEntNetAppleTalk); + CFRelease(interface); + + dict = cache_SCDynamicStoreCopyValue(store, key); + if (dict) { + if (isA_CFDictionary(dict)) { + newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict); + } + CFRelease(dict); + } + + if (!newDict) { + newDict = CFDictionaryCreateMutable(NULL, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + } + + /* Update zone value in cache */ + newZone = CFStringCreateWithPascalString(NULL, (ConstStr255Param)&(aEvent->node_data.zone), kCFStringEncodingMacRoman); + + CFDictionarySetValue(newDict, kSCPropNetAppleTalkDefaultZone, newZone); + + CFRelease(newZone); + + /* update cache */ + cache_SCDynamicStoreSetValue(store, key, newDict); + CFRelease(newDict); + CFRelease(key); + return; +} + + +__private_extern__ +void +interface_update_shutdown_atalk() +{ + CFStringRef cacheKey; + CFDictionaryRef dict; + CFArrayRef ifList = NULL; + CFIndex count, index; + CFStringRef interface; + CFStringRef key; + + cacheKey = SCDynamicStoreKeyCreateNetworkInterface(NULL, + kSCDynamicStoreDomainState); + + dict = cache_SCDynamicStoreCopyValue(store, cacheKey); + CFRelease(cacheKey); + + if (dict) { + if (isA_CFDictionary(dict)) { + /*get a list of the interfaces*/ + ifList = isA_CFArray(CFDictionaryGetValue(dict, kSCDynamicStorePropNetInterfaces)); + if (ifList) { + count = CFArrayGetCount(ifList); + + /*iterate through list and remove AppleTalk data*/ + for (index = 0; index < count; index++) { + interface = CFArrayGetValueAtIndex(ifList, index); + key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, + kSCDynamicStoreDomainState, + interface, + kSCEntNetAppleTalk); + cache_SCDynamicStoreRemoveValue(store, key); + CFRelease(key); + } + } + } + CFRelease(dict); + } + + return; +}