#include "eventmon.h"
#include "cache.h"
#include "ev_appletalk.h"
#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;
if ((fd = socket(AF_APPLETALK, SOCK_RAW, 0)) == -1)
return -1;
strncpy(cfg->ifr_name, if_name, sizeof(cfg->ifr_name));
if (ioctl(fd, AIOCGETIFCFG, (caddr_t)cfg) == -1) {
(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);
}
network_changed = TRUE;
}
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) == -1) {
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;
}
if (if_name) {
if (strncmp(if_name, ifa->ifa_name, IFNAMSIZ) == 0) {
interfaceFound = TRUE;
} else {
continue;
}
}
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;
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);
}
zone = CFStringCreateWithPascalString(NULL,
(ConstStr255Param)&cfg.zonename,
kCFStringEncodingMacRoman);
CFDictionarySetValue(newDict, kSCPropNetAppleTalkDefaultZone, zone);
CFRelease(zone);
}
CFDictionarySetValue(newIFs, key, newDict);
CFRelease(newDict);
CFRelease(key);
}
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;
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);
}
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);
cache_SCDynamicStoreSetValue(store, key, newDict);
network_changed = TRUE;
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;
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);
}
newZone = CFStringCreateWithPascalString(NULL, (ConstStr255Param)&(aEvent->node_data.zone), kCFStringEncodingMacRoman);
CFDictionarySetValue(newDict, kSCPropNetAppleTalkDefaultZone, newZone);
CFRelease(newZone);
cache_SCDynamicStoreSetValue(store, key, newDict);
network_changed = TRUE;
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)) {
ifList = isA_CFArray(CFDictionaryGetValue(dict, kSCPropNetInterfaces));
if (ifList) {
count = CFArrayGetCount(ifList);
for (index = 0; index < count; index++) {
interface = CFArrayGetValueAtIndex(ifList, index);
key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
kSCDynamicStoreDomainState,
interface,
kSCEntNetAppleTalk);
cache_SCDynamicStoreRemoveValue(store, key);
network_changed = TRUE;
CFRelease(key);
}
}
}
CFRelease(dict);
}
return;
}