#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/IOBSD.h>
#include <IOKit/network/IONetworkLib.h>
#include <IOKit/network/IONetworkInterface.h>
#include <IOKit/network/IONetworkController.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <mach/mach_interface.h>
IOReturn IONetworkOpen(io_object_t obj, io_connect_t * con)
{
return IOServiceOpen(obj, mach_task_self(), kIONUCType, con);
}
IOReturn IONetworkClose(io_connect_t con)
{
return IOServiceClose(con);
}
IOReturn IONetworkWriteData(io_connect_t con,
IONDHandle dataHandle,
UInt8 * srcBuf,
UInt32 inSize)
{
IOReturn kr;
if (!srcBuf || !inSize)
return kIOReturnBadArgument;
uint64_t data = dataHandle;
kr = IOConnectCallMethod(con, kIONUCWriteNetworkDataIndex,
&data, 1, srcBuf, (size_t) inSize, NULL, NULL, NULL, NULL);
return kr;
}
IOReturn IONetworkReadData(io_connect_t con,
IONDHandle dataHandle,
UInt8 * destBuf,
UInt32 * inOutSizeP)
{
IOReturn kr;
if (!destBuf || !inOutSizeP)
return kIOReturnBadArgument;
uint64_t data = dataHandle;
size_t size = *inOutSizeP;
kr = IOConnectCallMethod(con, kIONUCReadNetworkDataIndex,
&data, 1, NULL, 0, NULL, NULL, destBuf, &size); *inOutSizeP = (UInt32) size;
return kr;
}
IOReturn IONetworkResetData(io_connect_t con, IONDHandle dataHandle)
{
IOReturn kr;
uint64_t data = dataHandle;
kr = IOConnectCallScalarMethod(con, kIONUCResetNetworkDataIndex,
&data, 1, NULL, NULL);
return kr;
}
IOReturn IONetworkGetDataCapacity(io_connect_t con,
IONDHandle dataHandle,
UInt32 * capacityP)
{
if (!capacityP)
return kIOReturnBadArgument;
uint64_t data = dataHandle;
uint64_t capacity = *capacityP;
uint32_t one = 1;
IOReturn kr = IOConnectCallScalarMethod(con,
kIONUCGetNetworkDataCapacityIndex, &data, 1, &capacity, &one);
*capacityP = (UInt32) capacity; return kr;
}
IOReturn IONetworkGetDataHandle(io_connect_t con,
const char * dataName,
IONDHandle * dataHandleP)
{
if (!dataName || !dataHandleP)
return kIOReturnBadArgument;
size_t handleSize = sizeof(*dataHandleP);
return IOConnectCallStructMethod(con, kIONUCGetNetworkDataHandleIndex,
dataName, strlen(dataName) + 1,
dataHandleP, &handleSize);
}
#define kIONetworkInterfaceProperties "IONetworkInterfaceProperties"
#define kIORequiredPacketFilters "IORequiredPacketFilters"
static void
GetDictionaryValueUsingKeysApplier( const void * value,
void * context )
{
CFDictionaryRef * dict = (CFDictionaryRef *) context;
if ( ( *dict ) &&
( CFGetTypeID(*dict) == CFDictionaryGetTypeID() ) )
*dict = CFDictionaryGetValue( *dict, value );
else
*dict = 0;
}
static CFTypeRef
GetDictionaryValueUsingKeys( CFDictionaryRef dict,
CFArrayRef keysArray,
CFTypeID typeID )
{
CFArrayApplyFunction( keysArray,
CFRangeMake(0, CFArrayGetCount(keysArray)),
GetDictionaryValueUsingKeysApplier,
&dict );
if ( dict && (CFGetTypeID(dict) != typeID) ) dict = 0;
return dict;
}
static CFDictionaryRef
CreateNestedDictionariesUsingKeys( CFArrayRef keysArray,
CFTypeRef value )
{
CFDictionaryRef dict = 0;
CFDictionaryRef prevDict;
CFIndex index, count;
CFStringRef keys[1];
CFTypeRef values[1];
count = CFArrayGetCount(keysArray);
for ( index = count - 1;
index >= 0;
index-- )
{
prevDict = dict;
keys[0] = CFArrayGetValueAtIndex( keysArray, index );
values[0] = ( prevDict ) ? prevDict : value;
dict = CFDictionaryCreate( NULL,
(void *) keys,
(void *) values,
1,
&kCFCopyStringDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks );
if ( prevDict ) CFRelease( prevDict );
if ( dict == 0 ) break;
}
return dict;
}
IOReturn
IONetworkGetPacketFiltersMask( io_connect_t connect,
const io_name_t filterGroup,
UInt32 * filtersMask,
IOOptionBits options )
{
IOReturn kr;
io_service_t service = 0;
CFMutableDictionaryRef dict = 0;
CFArrayRef keysArray = 0;
CFStringRef group = 0;
CFStringRef keys[2];
CFTypeRef value;
do {
*filtersMask = 0;
kr = IOConnectGetService( connect, &service );
if ( kr != kIOReturnSuccess ) break;
if ( kIONetworkSupportedPacketFilters & options )
{
io_service_t parentService;
kr = IORegistryEntryGetParentEntry( service, kIOServicePlane,
&parentService );
if ( kr != kIOReturnSuccess ) break;
IOObjectRelease( service );
service = parentService;
}
kr = IORegistryEntryCreateCFProperties( service,
&dict,
kCFAllocatorDefault,
kNilOptions );
if ( kr != kIOReturnSuccess ) break;
group = CFStringCreateWithCString( kCFAllocatorDefault, filterGroup,
CFStringGetSystemEncoding() );
if ( group == 0 )
{
kr = kIOReturnNoMemory;
break;
}
keys[0] = (kIONetworkSupportedPacketFilters & options) ?
CFSTR( kIOPacketFilters ) :
CFSTR( kIORequiredPacketFilters );
keys[1] = group;
keysArray = CFArrayCreate( NULL, (void *)keys, 2, &kCFTypeArrayCallBacks );
if ( keysArray == 0 )
{
kr = kIOReturnNoMemory;
break;
}
value = GetDictionaryValueUsingKeys( dict, keysArray, CFNumberGetTypeID() );
if ( value == 0 )
{
kr = kIOReturnNotFound;
break;
}
CFNumberGetValue( (CFNumberRef)value, kCFNumberSInt32Type, filtersMask );
}
while ( 0 );
if ( dict ) CFRelease( dict );
if ( group ) CFRelease( group );
if ( keysArray ) CFRelease( keysArray );
if ( service ) IOObjectRelease( service );
return kr;
}
IOReturn
IONetworkSetPacketFiltersMask( io_connect_t connect,
const io_name_t filterGroup,
UInt32 filtersMask,
IOOptionBits options __unused )
{
IOReturn kr = kIOReturnNoMemory;
CFStringRef keys[3];
CFArrayRef keysArray = 0;
CFStringRef group = 0;
CFNumberRef num = 0;
CFDictionaryRef dict = 0;
do {
num = CFNumberCreate( kCFAllocatorDefault,
kCFNumberSInt32Type,
&filtersMask );
if ( num == 0 ) break;
group = CFStringCreateWithCString( kCFAllocatorDefault, filterGroup,
CFStringGetSystemEncoding() );
if ( group == 0 ) break;
keys[0] = CFSTR( kIONetworkInterfaceProperties );
keys[1] = CFSTR( kIORequiredPacketFilters );
keys[2] = group;
keysArray = CFArrayCreate( NULL, (void *)keys, 3, &kCFTypeArrayCallBacks );
if ( keysArray == 0 ) break;
dict = CreateNestedDictionariesUsingKeys( keysArray, num );
if ( dict == 0 ) break;
kr = IOConnectSetCFProperties( connect, dict );
}
while ( 0 );
if ( num ) CFRelease( num );
if ( group ) CFRelease( group );
if ( keysArray ) CFRelease( keysArray );
if ( dict ) CFRelease( dict );
return kr;
}