1/* 2 * Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23/* 24 * BLIsValidNetworkInterface.c 25 * bless 26 * 27 * Created by Shantonu Sen on 11/15/05. 28 * Copyright 2005-2007 Apple Inc. All Rights Reserved. 29 * 30 */ 31 32#import <mach/mach_error.h> 33 34#import <IOKit/IOKitLib.h> 35#import <IOKit/IOKitKeys.h> 36#import <IOKit/network/IONetworkInterface.h> 37#import <IOKit/network/IONetworkController.h> 38#import <IOKit/network/IONetworkMedium.h> 39#import <IOKit/IOBSD.h> 40 41#include <CoreFoundation/CoreFoundation.h> 42 43#include <sys/socket.h> 44#include <net/if.h> 45 46#include "bless.h" 47#include "bless_private.h" 48 49bool isInterfaceLinkUp(BLContextPtr context, 50 io_service_t service); 51 52bool BLIsValidNetworkInterface(BLContextPtr context, 53 const char *ifname) 54{ 55 56 io_service_t interface = IO_OBJECT_NULL; 57 CFMutableDictionaryRef matchingDict = NULL, propDict = NULL; 58 CFStringRef bsdName; 59 60 bsdName = CFStringCreateWithCString(kCFAllocatorDefault, 61 ifname, 62 kCFStringEncodingUTF8); 63 if(bsdName == NULL) { 64 contextprintf(context, kBLLogLevelError, "Could not get interpret interface as C string\n"); 65 return false; 66 } 67 68 matchingDict = IOServiceMatching(kIONetworkInterfaceClass); 69 propDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 70 &kCFTypeDictionaryKeyCallBacks, 71 &kCFTypeDictionaryValueCallBacks); 72 73 CFDictionaryAddValue(propDict, CFSTR(kIOBSDNameKey), bsdName); 74 CFDictionaryAddValue(matchingDict, CFSTR(kIOPropertyMatchKey), propDict); 75 CFRelease(propDict); 76 CFRelease(bsdName); 77 78 interface = IOServiceGetMatchingService(kIOMasterPortDefault, matchingDict); 79 if(interface == IO_OBJECT_NULL) { 80 contextprintf(context, kBLLogLevelError, "Could not get interface for %s\n", 81 ifname); 82 return false; 83 } 84 85 if(isInterfaceLinkUp(context, interface)) { 86 contextprintf(context, kBLLogLevelVerbose, "Interface for %s is valid\n", 87 ifname); 88 89 } else { 90 IOObjectRelease(interface); 91 92 contextprintf(context, kBLLogLevelError, "Interface for %s is not valid\n", 93 ifname); 94 95 return false; 96 } 97 98 IOObjectRelease(interface); 99 100 return true; 101} 102 103bool isInterfaceLinkUp(BLContextPtr context, 104 io_service_t serv) 105{ 106 CFTypeRef linkStatus, builtin, netbootable; 107 bool hasLink, isbootable = false; 108 109 builtin = IORegistryEntryCreateCFProperty(serv, CFSTR(kIOBuiltin), 110 kCFAllocatorDefault, 0); 111 112 if (builtin && CFGetTypeID(builtin) == CFBooleanGetTypeID() 113 && CFEqual(builtin, kCFBooleanTrue)) { 114 isbootable = true; 115 } 116 if (builtin) CFRelease(builtin); 117 118 if (!isbootable) { 119 netbootable = IORegistryEntrySearchCFProperty(serv, kIOServicePlane, CFSTR("ioNetBootable"), 120 kCFAllocatorDefault, kIORegistryIterateRecursively|kIORegistryIterateParents); 121 122 if (netbootable && CFGetTypeID(netbootable) == CFDataGetTypeID()) { 123 isbootable = true; 124 } 125 if (netbootable) CFRelease(netbootable); 126 } 127 128 if(!isbootable) { 129 contextprintf(context, kBLLogLevelError, "Interface is not built-in\n"); 130 131 return false; 132 } 133 134 135 linkStatus = IORegistryEntrySearchCFProperty(serv, kIOServicePlane, 136 CFSTR(kIOLinkStatus), 137 kCFAllocatorDefault, 138 kIORegistryIterateRecursively|kIORegistryIterateParents); 139 if(linkStatus == NULL) { 140 hasLink = false; 141 } else { 142 if(CFGetTypeID(linkStatus) != CFNumberGetTypeID()) { 143 hasLink = false; 144 } else { 145 uint32_t linkNum; 146 147 if(!CFNumberGetValue(linkStatus, kCFNumberSInt32Type, &linkNum)) { 148 hasLink = false; 149 } else { 150 if((linkNum & (kIONetworkLinkValid|kIONetworkLinkActive)) 151 == (kIONetworkLinkValid|kIONetworkLinkActive)) { 152 hasLink = true; 153 } else { 154 hasLink = false; 155 } 156 } 157 } 158 CFRelease(linkStatus); 159 } 160 161 contextprintf(context, kBLLogLevelVerbose, "Interface %s an active link\n", 162 hasLink ? "has" : "does not have"); 163 164 if(hasLink) { 165 return true; 166 } else { 167 return false; 168 } 169} 170 171