2010-10-19 38 views

Répondre

2

Ce fil peu adapté mon problème:

http://discussions.apple.com/thread.jspa?messageID=10935410&tstart=0

Ce fil a beaucoup aidé:

https://lists.isc.org/pipermail/dhcp-hackers/2007-September/000767.html

parce que le fil mentionne finalement que getifaddrs() doivent être utilisés à la place. La page de manuel sur Ubuntu 10.04 avait un bon exemple de comment utiliser getifaddrs et l'utiliser comme référence m'a aidé à comprendre le code qui a fonctionné sur Mac et Linux. Je ne veux pas que quelqu'un d'autre gaspille du temps sur quelque chose d'aussi simple, alors je poste et je me réponds ici. En espérant que mon message vous aide ...

7

Le mécanisme pour obtenir des adresses MAC est entièrement différent sur les systèmes d'exploitation dérivés de BSD que sur Linux. Cela inclut OS X.

Code est ici j'utiliser qui fonctionne sur Linux et OS X, et probablement sur les BSDs aussi:

#if defined(HAVE_SIOCGIFHWADDR) 
bool get_mac_address(char* mac_addr, const char* if_name = "eth0") 
{ 
    struct ifreq ifinfo; 
    strcpy(ifinfo.ifr_name, if_name); 
    int sd = socket(AF_INET, SOCK_DGRAM, 0); 
    int result = ioctl(sd, SIOCGIFHWADDR, &ifinfo); 
    close(sd); 

    if ((result == 0) && (ifinfo.ifr_hwaddr.sa_family == 1)) { 
     memcpy(mac_addr, ifinfo.ifr_hwaddr.sa_data, IFHWADDRLEN); 
     return true; 
    } 
    else { 
     return false; 
    } 
} 
#elif defined(HAVE_GETIFADDRS) 
bool get_mac_address(char* mac_addr, const char* if_name = "en0") 
{ 
    ifaddrs* iflist; 
    bool found = false; 
    if (getifaddrs(&iflist) == 0) { 
     for (ifaddrs* cur = iflist; cur; cur = cur->ifa_next) { 
      if ((cur->ifa_addr->sa_family == AF_LINK) && 
        (strcmp(cur->ifa_name, if_name) == 0) && 
        cur->ifa_addr) { 
       sockaddr_dl* sdl = (sockaddr_dl*)cur->ifa_addr; 
       memcpy(mac_addr, LLADDR(sdl), sdl->sdl_alen); 
       found = true; 
       break; 
      } 
     } 

     freeifaddrs(iflist); 
    } 
    return found; 
} 
#else 
# error no definition for get_mac_address() on this platform! 
#endif 

Il est à vous de trouver comment obtenir le droit HAVE_* macro défini pour la plate-forme. Il m'arrive d'utiliser autoconf pour cela, mais vous pouvez avoir une autre façon de gérer les différences de plate-forme.

Notez que le paramètre de nom d'interface par défaut pour ces fonctions est la valeur par défaut pour la première interface Ethernet sur les boîtes Linux et OS X. Vous devrez peut-être surcharger ceci pour d'autres systèmes d'exploitation, ou passer une autre valeur si vous êtes intéressé par l'adresse MAC pour une interface différente.

11

Copier-coller pour main.c et gcc main.c && ./a.out devrait fonctionner (liste toutes les interfaces réseau, leur ipv4/6 adresse, masque de réseau et adresse MAC si elle est associée):

fonctionne très bien sur Mac OS X et iOS iPad/iPhone:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <arpa/inet.h> 
#include <netinet/in.h> 
#include <net/if.h> 
#include <net/if_dl.h> 
#include <ifaddrs.h> 
#include <errno.h> 

int main() { 
    struct ifaddrs *if_addrs = NULL; 
    struct ifaddrs *if_addr = NULL; 
    void *tmp = NULL; 
    char buf[INET6_ADDRSTRLEN]; 
    if (0 == getifaddrs(&if_addrs)) {  
    for (if_addr = if_addrs; if_addr != NULL; if_addr = if_addr->ifa_next) { 

     printf("name : %s\n", if_addr->ifa_name); 

     // Address 
     if (if_addr->ifa_addr->sa_family == AF_INET) { 
     tmp = &((struct sockaddr_in *)if_addr->ifa_addr)->sin_addr; 
     } else { 
     tmp = &((struct sockaddr_in6 *)if_addr->ifa_addr)->sin6_addr; 
     } 
     printf("addr : %s\n", 
      inet_ntop(if_addr->ifa_addr->sa_family, 
         tmp, 
         buf, 
         sizeof(buf))); 

     // Mask 
     if (if_addr->ifa_netmask != NULL) { 
     if (if_addr->ifa_netmask->sa_family == AF_INET) { 
      tmp = &((struct sockaddr_in *)if_addr->ifa_netmask)->sin_addr; 
     } else { 
      tmp = &((struct sockaddr_in6 *)if_addr->ifa_netmask)->sin6_addr; 
     } 
     printf("mask : %s\n", 
       inet_ntop(if_addr->ifa_netmask->sa_family, 
         tmp, 
         buf, 
         sizeof(buf))); 
     } 

     // MAC address 
     if (if_addr->ifa_addr != NULL && if_addr->ifa_addr->sa_family == AF_LINK) { 
     struct sockaddr_dl* sdl = (struct sockaddr_dl *)if_addr->ifa_addr; 
     unsigned char mac[6]; 
     if (6 == sdl->sdl_alen) { 
      memcpy(mac, LLADDR(sdl), sdl->sdl_alen); 
      printf("mac : %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 
     } 
     } 

     printf("\n"); 
    } 
    freeifaddrs(if_addrs); 
    if_addrs = NULL; 
    } else { 
    printf("getifaddrs() failed with errno = %i %s\n", errno, strerror(errno)); 
    return -1; 
    } 
}