2010-10-19 11 views

risposta

2

Questo thread ha trovato un po 'il mio problema:

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

Questo thread ha aiutato molto:

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

perché quel filo alla fine menziona che getifaddrs() devono essere utilizzati al posto. La pagina man su Ubuntu 10.04 aveva un ottimo esempio di come usare getifaddrs e usarlo come riferimento mi ha aiutato a capire il codice che funzionava sia su Mac che su Linux. Non voglio che nessun altro sprechi tempo in qualcosa di così semplice, quindi sto postando e rispondendo a me stesso qui. Sperando che il mio post ti aiuti ...

7

Il meccanismo per ottenere indirizzi MAC è completamente diverso sui sistemi operativi derivati ​​da BSD che su Linux. Questo include OS X.

Ecco il codice che uso che funziona su Linux e OS X, e probabilmente sulle BSD, troppo:

#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 

E 'a voi per capire come ottenere il giusto HAVE_* macro definito per la piattaforma. Mi è capitato di utilizzare autoconf per questo, ma potresti avere un altro modo di affrontare le differenze di piattaforma.

Si noti che il parametro del nome dell'interfaccia predefinito per queste funzioni è il valore predefinito per la prima interfaccia Ethernet su Linux e OS X box. Potrebbe essere necessario sovrascriverlo per altri sistemi operativi o passare un altro valore se si è interessati all'indirizzo MAC per un'interfaccia diversa.

11

Copia-incolla per main.c e gcc main.c && ./a.out dovrebbe funzionare (elenca tutte le interfacce di rete, la loro ipv4/6 indirizzo, maschera di rete e indirizzo MAC se associata):

funziona bene su Mac OSX e 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; 
    } 
}