From 52ec19b00fbcd40a19c24dcecd87764b5b6739aa Mon Sep 17 00:00:00 2001 From: malaterre Date: Fri, 7 Jan 2005 23:59:12 +0000 Subject: [PATCH] ENH: Addingh MACOSX version --- src/gdcmUtil.cxx | 192 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 190 insertions(+), 2 deletions(-) diff --git a/src/gdcmUtil.cxx b/src/gdcmUtil.cxx index c48efce5..5930aff4 100644 --- a/src/gdcmUtil.cxx +++ b/src/gdcmUtil.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmUtil.cxx,v $ Language: C++ - Date: $Date: 2005/01/07 23:44:46 $ - Version: $Revision: 1.80 $ + Date: $Date: 2005/01/07 23:59:12 $ + Version: $Revision: 1.81 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -358,6 +358,160 @@ typedef BOOL(WINAPI * pSnmpExtensionInitEx) ( #include #endif +#ifdef __APPLE__ + +#include + +#include +#include +#include +#include + +static kern_return_t FindEthernetInterfaces(io_iterator_t *matchingServices); +static kern_return_t GetMACAddress(io_iterator_t intfIterator, UInt8 *MACAddress); + +// Returns an iterator containing the primary (built-in) Ethernet interface. The caller is responsible for +// releasing the iterator after the caller is done with it. +static kern_return_t FindEthernetInterfaces(io_iterator_t *matchingServices) +{ + kern_return_t kernResult; + mach_port_t masterPort; + CFMutableDictionaryRef matchingDict; + CFMutableDictionaryRef propertyMatchDict; + + // Retrieve the Mach port used to initiate communication with I/O Kit + kernResult = IOMasterPort(MACH_PORT_NULL, &masterPort); + if (KERN_SUCCESS != kernResult) + { + printf("IOMasterPort returned %d\n", kernResult); + return kernResult; + } + + // Ethernet interfaces are instances of class kIOEthernetInterfaceClass. + // IOServiceMatching is a convenience function to create a dictionary with the key kIOProviderClassKey and + // the specified value. + matchingDict = IOServiceMatching(kIOEthernetInterfaceClass); + + // Note that another option here would be: + // matchingDict = IOBSDMatching("en0"); + + if (NULL == matchingDict) + { + printf("IOServiceMatching returned a NULL dictionary.\n"); + } + else { + // Each IONetworkInterface object has a Boolean property with the key kIOPrimaryInterface. Only the + // primary (built-in) interface has this property set to TRUE. + + // IOServiceGetMatchingServices uses the default matching criteria defined by IOService. This considers + // only the following properties plus any family-specific matching in this order of precedence + // (see IOService::passiveMatch): + // + // kIOProviderClassKey (IOServiceMatching) + // kIONameMatchKey (IOServiceNameMatching) + // kIOPropertyMatchKey + // kIOPathMatchKey + // kIOMatchedServiceCountKey + // family-specific matching + // kIOBSDNameKey (IOBSDNameMatching) + // kIOLocationMatchKey + + // The IONetworkingFamily does not define any family-specific matching. This means that in + // order to have IOServiceGetMatchingServices consider the kIOPrimaryInterface property, we must + // add that property to a separate dictionary and then add that to our matching dictionary + // specifying kIOPropertyMatchKey. + + propertyMatchDict = CFDictionaryCreateMutable( kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + if (NULL == propertyMatchDict) + { + printf("CFDictionaryCreateMutable returned a NULL dictionary.\n"); + } + else { + // Set the value in the dictionary of the property with the given key, or add the key + // to the dictionary if it doesn't exist. This call retains the value object passed in. + CFDictionarySetValue(propertyMatchDict, CFSTR(kIOPrimaryInterface), kCFBooleanTrue); + + // Now add the dictionary containing the matching value for kIOPrimaryInterface to our main + // matching dictionary. This call will retain propertyMatchDict, so we can release our reference + // on propertyMatchDict after adding it to matchingDict. + CFDictionarySetValue(matchingDict, CFSTR(kIOPropertyMatchKey), propertyMatchDict); + CFRelease(propertyMatchDict); + } + } + + // IOServiceGetMatchingServices retains the returned iterator, so release the iterator when we're done with it. + // IOServiceGetMatchingServices also consumes a reference on the matching dictionary so we don't need to release + // the dictionary explicitly. + kernResult = IOServiceGetMatchingServices(masterPort, matchingDict, matchingServices); + if (KERN_SUCCESS != kernResult) + { + printf("IOServiceGetMatchingServices returned %d\n", kernResult); + } + + return kernResult; +} + +// Given an iterator across a set of Ethernet interfaces, return the MAC address of the last one. +// If no interfaces are found the MAC address is set to an empty string. +// In this sample the iterator should contain just the primary interface. +static kern_return_t GetMACAddress_MAC(io_iterator_t intfIterator, UInt8 *MACAddress) +{ + io_object_t intfService; + io_object_t controllerService; + kern_return_t kernResult = KERN_FAILURE; + + // Initialize the returned address + bzero(MACAddress, kIOEthernetAddressSize); + + // IOIteratorNext retains the returned object, so release it when we're done with it. + while (intfService = IOIteratorNext(intfIterator)) + { + CFTypeRef MACAddressAsCFData; + + // IONetworkControllers can't be found directly by the IOServiceGetMatchingServices call, + // since they are hardware nubs and do not participate in driver matching. In other words, + // registerService() is never called on them. So we've found the IONetworkInterface and will + // get its parent controller by asking for it specifically. + + // IORegistryEntryGetParentEntry retains the returned object, so release it when we're done with it. + kernResult = IORegistryEntryGetParentEntry( intfService, + kIOServicePlane, + &controllerService ); + + if (KERN_SUCCESS != kernResult) + { + printf("IORegistryEntryGetParentEntry returned 0x%08x\n", kernResult); + } + else { + // Retrieve the MAC address property from the I/O Registry in the form of a CFData + MACAddressAsCFData = IORegistryEntryCreateCFProperty( controllerService, + CFSTR(kIOMACAddress), + kCFAllocatorDefault, + 0); + if (MACAddressAsCFData) + { + CFShow(MACAddressAsCFData); // for display purposes only; output goes to stderr + + // Get the raw bytes of the MAC address from the CFData + CFDataGetBytes(MACAddressAsCFData, CFRangeMake(0, kIOEthernetAddressSize), MACAddress); + CFRelease(MACAddressAsCFData); + } + + // Done with the parent Ethernet controller object so we release it. + (void) IOObjectRelease(controllerService); + } + + // Done with the Ethernet interface object so we release it. + (void) IOObjectRelease(intfService); + } + + return kernResult; +} +#endif + long GetMacAddrSys ( u_char *addr) { #ifdef _WIN32 @@ -534,6 +688,7 @@ long GetMacAddrSys ( u_char *addr) #endif //_WIN32 /* implementation for Linux */ +// FreeBSD might be similar ?? #ifdef __linux__ struct ifreq ifr; struct ifreq *IFR; @@ -636,7 +791,40 @@ long GetMacAddrSys ( u_char *addr) return 0; #endif //_AIX +#ifdef __APPLE__ + kern_return_t kernResult = KERN_SUCCESS; // on PowerPC this is an int (4 bytes) +/* + * error number layout as follows (see mach/error.h and IOKit/IOReturn.h): + * + * hi lo + * | system(6) | subsystem(12) | code(14) | + */ + + io_iterator_t intfIterator; + //UInt8 MACAddress[ kIOEthernetAddressSize ]; + + kernResult = FindEthernetInterfaces(&intfIterator); + + if (KERN_SUCCESS != kernResult) + { + printf("FindEthernetInterfaces returned 0x%08x\n", kernResult); + } + else { + kernResult = GetMACAddress_MAC(intfIterator, addr); + + if (KERN_SUCCESS != kernResult) + { + printf("GetMACAddress returned 0x%08x\n", kernResult); + } + } + + (void) IOObjectRelease(intfIterator); // Release the iterator. + + return kernResult; +#endif //APPLE + /* Not implemented platforms */ + memset(addr,0,6); return -1; } -- 2.45.1