]> Creatis software - gdcm.git/commitdiff
ENH: Addingh MACOSX version
authormalaterre <malaterre>
Fri, 7 Jan 2005 23:59:12 +0000 (23:59 +0000)
committermalaterre <malaterre>
Fri, 7 Jan 2005 23:59:12 +0000 (23:59 +0000)
src/gdcmUtil.cxx

index c48efce51cc0cec2cf6939e6d4a866e69173f410..5930aff41988b79e8e2a096630902f973e8b29e8 100644 (file)
@@ -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 <sys/kinfo.h>
 #endif
 
+#ifdef __APPLE__
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include <IOKit/IOKitLib.h>
+#include <IOKit/network/IOEthernetInterface.h>
+#include <IOKit/network/IONetworkInterface.h>
+#include <IOKit/network/IOEthernetController.h>
+
+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;
 }