/* * 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; }