--- /dev/null
+/*
+ * 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 <ajn@apple.com>
+ * - 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;
+}