X-Git-Url: https://git.saurik.com/apple/configd.git/blobdiff_plain/4c5e92e2493bdfbbce40e998f3b607c72c47af2c..dbf6a266c384fc8b55e00a396eebe5cb62e21547:/Plugins/KernelEventMonitor/ev_dlil.c diff --git a/Plugins/KernelEventMonitor/ev_dlil.c b/Plugins/KernelEventMonitor/ev_dlil.c new file mode 100644 index 0000000..516fe99 --- /dev/null +++ b/Plugins/KernelEventMonitor/ev_dlil.c @@ -0,0 +1,291 @@ +/* + * 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_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 new status available, update cache */ + if (active == NULL) { + CFDictionaryRemoveValue(newDict, kSCPropNetLinkActive); + } else { + CFDictionarySetValue(newDict, kSCPropNetLinkActive, active); + } + if (attach == TRUE) { + /* the interface was attached, remove stale state */ + CFDictionaryRemoveValue(newDict, kSCPropNetLinkDetaching); + } + + /* update status */ + 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) { + /* if media status not available for this interface */ + goto done; + } + + if (ifm.ifm_count == 0) { + /* no media types */ + goto done; + } + + if (!(ifm.ifm_status & IFM_AVALID)) { + /* if active bit not valid */ + 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) + ) { + /* we're not tracking this interface */ + 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; +}