1/* 2 * Copyright (c) 1999-2000 Apple Computer, 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 * HISTORY 25 * 26 */ 27 28#include <CoreFoundation/CoreFoundation.h> 29#include <IOKit/IOKitLib.h> 30#include <IOKit/IOBSD.h> 31#include <IOKit/network/IONetworkLib.h> 32#include <IOKit/network/IONetworkInterface.h> 33#include <IOKit/network/IONetworkController.h> 34#include <ctype.h> 35#include <stdlib.h> 36#include <stdio.h> 37#include <mach/mach_interface.h> 38 39//--------------------------------------------------------------------------- 40// IONetworkOpen - Open a connection to an IONetworkInterface object. 41// An IONetworkUserClient object is created to manage 42// the connection. 43 44IOReturn IONetworkOpen(io_object_t obj, io_connect_t * con) 45{ 46 return IOServiceOpen(obj, mach_task_self(), kIONUCType, con); 47} 48 49//--------------------------------------------------------------------------- 50// IONetworkClose - Close the connection to an IONetworkInterface object. 51 52IOReturn IONetworkClose(io_connect_t con) 53{ 54 return IOServiceClose(con); 55} 56 57//--------------------------------------------------------------------------- 58// IONetworkWriteData - Write to the buffer of a network data object. 59 60IOReturn IONetworkWriteData(io_connect_t con, 61 IONDHandle dataHandle, 62 UInt8 * srcBuf, 63 UInt32 inSize) 64{ 65 IOReturn kr; 66 67 if (!srcBuf || !inSize) 68 return kIOReturnBadArgument; 69 70 uint64_t data = dataHandle; 71 kr = IOConnectCallMethod(con, kIONUCWriteNetworkDataIndex, 72 &data, 1, // input[], inputCount 73 srcBuf, (size_t) inSize,// inputStruct, inputStructCnt 74 NULL, NULL, // output scalar 75 NULL, NULL); // output struct 76 77 return kr; 78} 79 80//--------------------------------------------------------------------------- 81// IONetworkReadData - Read the buffer of a network data object. 82 83IOReturn IONetworkReadData(io_connect_t con, 84 IONDHandle dataHandle, 85 UInt8 * destBuf, 86 UInt32 * inOutSizeP) 87{ 88 IOReturn kr; 89 90 if (!destBuf || !inOutSizeP) 91 return kIOReturnBadArgument; 92 93 uint64_t data = dataHandle; 94 size_t size = *inOutSizeP; 95 kr = IOConnectCallMethod(con, kIONUCReadNetworkDataIndex, 96 &data, 1, // input[], inputCount 97 NULL, 0, // inputStruct, inputStructCnt 98 NULL, NULL, // output scalar 99 destBuf, &size);// output struct 100 *inOutSizeP = (UInt32) size; 101 102 return kr; 103} 104 105//--------------------------------------------------------------------------- 106// IONetworkResetData - Fill the buffer of a network data object with zeroes. 107 108IOReturn IONetworkResetData(io_connect_t con, IONDHandle dataHandle) 109{ 110 IOReturn kr; 111 112 uint64_t data = dataHandle; 113 kr = IOConnectCallScalarMethod(con, kIONUCResetNetworkDataIndex, 114 &data, 1, // input[], inputCount 115 NULL, NULL); 116 117 return kr; 118} 119 120//--------------------------------------------------------------------------- 121// IONetworkGetDataCapacity - Get the capacity (in bytes) of a network data 122// object. 123 124IOReturn IONetworkGetDataCapacity(io_connect_t con, 125 IONDHandle dataHandle, 126 UInt32 * capacityP) 127{ 128 if (!capacityP) 129 return kIOReturnBadArgument; 130 131 uint64_t data = dataHandle; 132 uint64_t capacity = *capacityP; 133 uint32_t one = 1; 134 IOReturn kr = IOConnectCallScalarMethod(con, 135 kIONUCGetNetworkDataCapacityIndex, &data, 1, &capacity, &one); 136 *capacityP = (UInt32) capacity; // XXX paul?: update for 64 bit? 137 return kr; 138} 139 140//--------------------------------------------------------------------------- 141// IONetworkGetDataHandle - Get the handle of a network data object with 142// the given name. 143 144IOReturn IONetworkGetDataHandle(io_connect_t con, 145 const char * dataName, 146 IONDHandle * dataHandleP) 147{ 148 if (!dataName || !dataHandleP) 149 return kIOReturnBadArgument; 150 151 size_t handleSize = sizeof(*dataHandleP); 152 return IOConnectCallStructMethod(con, kIONUCGetNetworkDataHandleIndex, 153 dataName, strlen(dataName) + 1, 154 dataHandleP, &handleSize); 155} 156 157//--------------------------------------------------------------------------- 158// Utility functions to manipulate nested dictionaries. 159 160#define kIONetworkInterfaceProperties "IONetworkInterfaceProperties" 161#define kIORequiredPacketFilters "IORequiredPacketFilters" 162 163static void 164GetDictionaryValueUsingKeysApplier( const void * value, 165 void * context ) 166{ 167 CFDictionaryRef * dict = (CFDictionaryRef *) context; 168 169 if ( ( *dict ) && 170 ( CFGetTypeID(*dict) == CFDictionaryGetTypeID() ) ) 171 *dict = CFDictionaryGetValue( *dict, value ); 172 else 173 *dict = 0; 174} 175 176static CFTypeRef 177GetDictionaryValueUsingKeys( CFDictionaryRef dict, 178 CFArrayRef keysArray, 179 CFTypeID typeID ) 180{ 181 CFArrayApplyFunction( keysArray, 182 CFRangeMake(0, CFArrayGetCount(keysArray)), 183 GetDictionaryValueUsingKeysApplier, 184 &dict ); 185 186 if ( dict && (CFGetTypeID(dict) != typeID) ) dict = 0; 187 188 return dict; 189} 190 191static CFDictionaryRef 192CreateNestedDictionariesUsingKeys( CFArrayRef keysArray, 193 CFTypeRef value ) 194{ 195 CFDictionaryRef dict = 0; 196 CFDictionaryRef prevDict; 197 CFIndex index, count; 198 CFStringRef keys[1]; 199 CFTypeRef values[1]; 200 201 count = CFArrayGetCount(keysArray); 202 for ( index = count - 1; 203 index >= 0; 204 index-- ) 205 { 206 prevDict = dict; 207 208 keys[0] = CFArrayGetValueAtIndex( keysArray, index ); 209 values[0] = ( prevDict ) ? prevDict : value; 210 211 dict = CFDictionaryCreate( NULL, 212 (void *) keys, 213 (void *) values, 214 1, 215 &kCFCopyStringDictionaryKeyCallBacks, 216 &kCFTypeDictionaryValueCallBacks ); 217 218 if ( prevDict ) CFRelease( prevDict ); 219 if ( dict == 0 ) break; 220 } 221 222 return dict; 223} 224 225//--------------------------------------------------------------------------- 226// IONetworkGetPacketFiltersMask 227 228IOReturn 229IONetworkGetPacketFiltersMask( io_connect_t connect, 230 const io_name_t filterGroup, 231 UInt32 * filtersMask, 232 IOOptionBits options ) 233{ 234 IOReturn kr; 235 io_service_t service = 0; 236 CFMutableDictionaryRef dict = 0; 237 CFArrayRef keysArray = 0; 238 CFStringRef group = 0; 239 CFStringRef keys[2]; 240 CFTypeRef value; 241 242 do { 243 *filtersMask = 0; 244 245 // Locate our service provider. 246 247 kr = IOConnectGetService( connect, &service ); 248 if ( kr != kIOReturnSuccess ) break; 249 250 if ( kIONetworkSupportedPacketFilters & options ) 251 { 252 io_service_t parentService; 253 kr = IORegistryEntryGetParentEntry( service, kIOServicePlane, 254 &parentService ); 255 if ( kr != kIOReturnSuccess ) break; 256 IOObjectRelease( service ); 257 service = parentService; 258 } 259 260 // Fetch properties from registry. 261 262 kr = IORegistryEntryCreateCFProperties( service, 263 &dict, 264 kCFAllocatorDefault, 265 kNilOptions ); 266 if ( kr != kIOReturnSuccess ) break; 267 268 group = CFStringCreateWithCString( kCFAllocatorDefault, filterGroup, 269 CFStringGetSystemEncoding() ); 270 if ( group == 0 ) 271 { 272 kr = kIOReturnNoMemory; 273 break; 274 } 275 276 // Create an array of keys to the value. 277 278 keys[0] = (kIONetworkSupportedPacketFilters & options) ? 279 CFSTR( kIOPacketFilters ) : 280 CFSTR( kIORequiredPacketFilters ); 281 keys[1] = group; 282 283 keysArray = CFArrayCreate( NULL, (void *)keys, 2, &kCFTypeArrayCallBacks ); 284 if ( keysArray == 0 ) 285 { 286 kr = kIOReturnNoMemory; 287 break; 288 } 289 290 value = GetDictionaryValueUsingKeys( dict, keysArray, CFNumberGetTypeID() ); 291 if ( value == 0 ) 292 { 293 kr = kIOReturnNotFound; 294 break; 295 } 296 297 CFNumberGetValue( (CFNumberRef)value, kCFNumberSInt32Type, filtersMask ); 298 } 299 while ( 0 ); 300 301 if ( dict ) CFRelease( dict ); 302 if ( group ) CFRelease( group ); 303 if ( keysArray ) CFRelease( keysArray ); 304 if ( service ) IOObjectRelease( service ); 305 306 return kr; 307} 308 309//--------------------------------------------------------------------------- 310// IONetworkSetPacketFiltersMask 311 312IOReturn 313IONetworkSetPacketFiltersMask( io_connect_t connect, 314 const io_name_t filterGroup, 315 UInt32 filtersMask, 316 IOOptionBits options __unused ) 317{ 318 IOReturn kr = kIOReturnNoMemory; 319 CFStringRef keys[3]; 320 CFArrayRef keysArray = 0; 321 CFStringRef group = 0; 322 CFNumberRef num = 0; 323 CFDictionaryRef dict = 0; 324 325 do { 326 num = CFNumberCreate( kCFAllocatorDefault, 327 kCFNumberSInt32Type, 328 &filtersMask ); 329 if ( num == 0 ) break; 330 331 group = CFStringCreateWithCString( kCFAllocatorDefault, filterGroup, 332 CFStringGetSystemEncoding() ); 333 if ( group == 0 ) break; 334 335 keys[0] = CFSTR( kIONetworkInterfaceProperties ); 336 keys[1] = CFSTR( kIORequiredPacketFilters ); 337 keys[2] = group; 338 339 keysArray = CFArrayCreate( NULL, (void *)keys, 3, &kCFTypeArrayCallBacks ); 340 if ( keysArray == 0 ) break; 341 342 dict = CreateNestedDictionariesUsingKeys( keysArray, num ); 343 if ( dict == 0 ) break; 344 345 kr = IOConnectSetCFProperties( connect, dict ); 346 } 347 while ( 0 ); 348 349 if ( num ) CFRelease( num ); 350 if ( group ) CFRelease( group ); 351 if ( keysArray ) CFRelease( keysArray ); 352 if ( dict ) CFRelease( dict ); 353 354 return kr; 355} 356