#include "eventmon.h"
#include "cache.h"
#include "ev_dlil.h"
static CFStringRef
create_interface_key(const char * if_name)
{
CFStringRef interface;
CFStringRef key;
interface = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingMacRoman);
key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
kSCDynamicStoreDomainState,
interface,
kSCEntNetLink);
CFRelease(interface);
return (key);
}
static CFMutableDictionaryRef
copy_entity(CFStringRef key)
{
CFDictionaryRef dict;
CFMutableDictionaryRef newDict = NULL;
dict = cache_SCDynamicStoreCopyValue(store, key);
if (dict != NULL) {
if (isA_CFDictionary(dict) != NULL) {
newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
}
CFRelease(dict);
}
if (newDict == NULL) {
newDict = CFDictionaryCreateMutable(NULL,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
}
return (newDict);
}
static void
interface_update_status(const char *if_name, CFBooleanRef active,
boolean_t attach)
{
CFStringRef key = NULL;
CFMutableDictionaryRef newDict = NULL;
CFBooleanRef state = NULL;
key = create_interface_key(if_name);
newDict = copy_entity(key);
state = isA_CFBoolean(CFDictionaryGetValue(newDict,
kSCPropNetLinkActive));
if (active == NULL) {
CFDictionaryRemoveValue(newDict, kSCPropNetLinkActive);
} else {
CFDictionarySetValue(newDict, kSCPropNetLinkActive, active);
}
if (attach == TRUE) {
CFDictionaryRemoveValue(newDict, kSCPropNetLinkDetaching);
}
if (CFDictionaryGetCount(newDict) > 0) {
cache_SCDynamicStoreSetValue(store, key, newDict);
} else {
cache_SCDynamicStoreRemoveValue(store, key);
}
CFRelease(key);
CFRelease(newDict);
return;
}
__private_extern__
void
interface_detaching(const char *if_name)
{
CFStringRef key;
CFMutableDictionaryRef newDict;
key = create_interface_key(if_name);
newDict = copy_entity(key);
CFDictionarySetValue(newDict, kSCPropNetLinkDetaching,
kCFBooleanTrue);
cache_SCDynamicStoreSetValue(store, key, newDict);
CFRelease(newDict);
CFRelease(key);
return;
}
static void
interface_remove(const char *if_name)
{
CFStringRef key;
key = create_interface_key(if_name);
cache_SCDynamicStoreRemoveValue(store, key);
CFRelease(key);
return;
}
__private_extern__
void
link_update_status(const char *if_name, boolean_t attach)
{
CFBooleanRef active = NULL;
struct ifmediareq ifm;
int sock;
sock = dgram_socket(AF_INET);
if (sock < 0) {
SCLog(TRUE, LOG_NOTICE, CFSTR("link_update_status: socket open failed, %s"), strerror(errno));
goto done;
}
bzero((char *)&ifm, sizeof(ifm));
(void) strncpy(ifm.ifm_name, if_name, sizeof(ifm.ifm_name));
if (ioctl(sock, SIOCGIFMEDIA, (caddr_t)&ifm) == -1) {
goto done;
}
if (ifm.ifm_count == 0) {
goto done;
}
if (!(ifm.ifm_status & IFM_AVALID)) {
goto done;
}
if (ifm.ifm_status & IFM_ACTIVE) {
active = kCFBooleanTrue;
} else {
active = kCFBooleanFalse;
}
done:
interface_update_status(if_name, active, attach);
if (sock >= 0)
close(sock);
return;
}
__private_extern__
void
link_add(const char *if_name)
{
CFStringRef interface;
CFStringRef cacheKey;
CFDictionaryRef dict;
CFMutableDictionaryRef newDict = NULL;
CFArrayRef ifList;
CFMutableArrayRef newIFList = NULL;
interface = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingMacRoman);
cacheKey = SCDynamicStoreKeyCreateNetworkInterface(NULL,
kSCDynamicStoreDomainState);
dict = cache_SCDynamicStoreCopyValue(store, cacheKey);
if (dict) {
if (isA_CFDictionary(dict)) {
newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
ifList = CFDictionaryGetValue(newDict, kSCDynamicStorePropNetInterfaces);
if (isA_CFArray(ifList)) {
newIFList = CFArrayCreateMutableCopy(NULL, 0, ifList);
}
}
CFRelease(dict);
}
if (!newDict) {
newDict = CFDictionaryCreateMutable(NULL,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
}
if (!newIFList) {
newIFList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
}
if (CFArrayContainsValue(newIFList,
CFRangeMake(0, CFArrayGetCount(newIFList)),
interface) == FALSE) {
CFArrayAppendValue(newIFList, interface);
CFDictionarySetValue(newDict,
kSCDynamicStorePropNetInterfaces,
newIFList);
}
cache_SCDynamicStoreSetValue(store, cacheKey, newDict);
link_update_status(if_name, TRUE);
CFRelease(cacheKey);
CFRelease(interface);
if (newDict) CFRelease(newDict);
if (newIFList) CFRelease(newIFList);
return;
}
__private_extern__
void
link_remove(const char *if_name)
{
CFStringRef interface;
CFStringRef cacheKey;
CFDictionaryRef dict;
CFMutableDictionaryRef newDict = NULL;
CFArrayRef ifList;
CFMutableArrayRef newIFList = NULL;
CFIndex i;
interface = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingMacRoman);
cacheKey = SCDynamicStoreKeyCreateNetworkInterface(NULL,
kSCDynamicStoreDomainState);
dict = cache_SCDynamicStoreCopyValue(store, cacheKey);
if (dict) {
if (isA_CFDictionary(dict)) {
newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
ifList = CFDictionaryGetValue(newDict, kSCDynamicStorePropNetInterfaces);
if (isA_CFArray(ifList)) {
newIFList = CFArrayCreateMutableCopy(NULL, 0, ifList);
}
}
CFRelease(dict);
}
if (!newIFList ||
((i = CFArrayGetFirstIndexOfValue(newIFList,
CFRangeMake(0, CFArrayGetCount(newIFList)),
interface)) == kCFNotFound)
) {
goto done;
}
CFArrayRemoveValueAtIndex(newIFList, i);
CFDictionarySetValue(newDict, kSCDynamicStorePropNetInterfaces, newIFList);
cache_SCDynamicStoreSetValue(store, cacheKey, newDict);
interface_remove(if_name);
done:
CFRelease(cacheKey);
CFRelease(interface);
if (newDict) CFRelease(newDict);
if (newIFList) CFRelease(newIFList);
return;
}