Jak pobrać adres MAC lokalnego interfejsu w systemie UNIX

// dla gcc
#include <sys/ioctl.h>  // ioctl(), SIOCGIFHWADDR
#include <net/if.h>     // ifreq, socket(), AF_INET, SOCK_DRAM

// jesli g++ : to jeszcze to:
#include <stdio.h>      // printf(),sprintf()
#include <unistd.h>     // close()
#include <string.h>     // strcpy()

#define HWADDR_NBYTES 6
#define HWADDR_LEN    18


char* hwaddr(char* ifname,char* buf){
  struct ifreq ifr;
  int i=socket(AF_INET,SOCK_DGRAM,0);
  if(i<0)return 0;
  strcpy(ifr.ifr_name,ifname);
  int j=ioctl(i,SIOCGIFHWADDR,&ifr);
  close(i);
  if(j<0)return 0;
  i=j=0;
  while(i<HWADDR_NBYTES){
    sprintf(buf+j,"%02X",((unsigned char*)(&ifr.ifr_hwaddr.sa_data))[i++]);
    if((j+=2)<HWADDR_LEN-1)buf[j++]=':';
  }
  return buf;
}


// ...

char mac[HWADDR_LEN];

if(hwaddr("eth0",mac))printf("mac adres eth0: %s\n",mac);

// ...

a tak to wygląda dla bsd
na podstawie: http://othermark.livejournal.com/3005.html (sprawdzone pod open i freebsd)

#include <stdio.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <net/if_dl.h>
#include <ifaddrs.h>

#define HWADDR_NBYTES 6
#define HWADDR_LEN    18

char* hwaddr(char* ifname,char* buf){
  *buf=0;
  struct ifaddrs* ifap;
  struct ifaddrs* ifaphead;
  unsigned char if_mac[HWADDR_NBYTES];
  if(getifaddrs(&ifaphead))return 0;
  ifap=ifaphead;
  while(ifap){
    if(ifap->ifa_addr->sa_family==AF_LINK && !strcmp(ifap->ifa_name,ifname) && ifap->ifa_addr){
      struct sockaddr_dl* sdl=(struct sockaddr_dl*)ifap->ifa_addr;
      memcpy(if_mac,LLADDR(sdl),6);
      break;
    }
    ifap=ifap->ifa_next;
  }
  freeifaddrs(ifaphead);
  if(!ifap)return 0;
  int i,j;
  i=j=0;
  while(i<HWADDR_NBYTES){
    sprintf(buf+j,"%02X",((unsigned char*)(&ifr.ifr_hwaddr.sa_data))[i++]);
    if((j+=2)<HWADDR_LEN-1)buf[j++]=':';
  }
  return buf;
}



// ...

char mac[HWADDR_LEN];

if(hwaddr("vic0",mac))printf("mac adres vic0: %s\n",mac);

// ...

w ostateczności połączenie może wyglądać np. tak:

char* hwaddr(char* ifname,char* buf){
#define HWADDR_NBYTES 6
  if(!buf)return 0;
  *buf=0;
  if(!ifname || !*ifname)return 0;
  int i,j;
#ifdef SIOCGIFHWADDR
  ifreq ifr;
  if((i=socket(AF_INET,SOCK_DGRAM,0))<0)return 0;
  strcpy(ifr.ifr_name,ifname);
  j=ioctl(i,SIOCGIFHWADDR,&ifr);
  close(i);
  if(j<0)return 0;
  unsigned char* if_mac=(unsigned char*)ifr.ifr_hwaddr.sa_data;  // tu if_mac jest wskaznikiem do statycznego bufora
#else
#ifdef AF_LINK
  struct ifaddrs* ifap;
  struct ifaddrs* ifaphead;
  unsigned char if_mac[HWADDR_NBYTES];  // tu if_mac JEST statycznym buforem
  if(getifaddrs(&ifaphead))return 0;
  ifap=ifaphead;
  while(ifap){
    if(ifap->ifa_addr->sa_family==AF_LINK && !strcmp(ifap->ifa_name,ifname) && ifap->ifa_addr){
      struct sockaddr_dl* sdl=(struct sockaddr_dl*)ifap->ifa_addr;
      memcpy(if_mac,LLADDR(sdl),6);
      break;
    }
    ifap=ifap->ifa_next;
  }
  freeifaddrs(ifaphead);
  if(!ifap)return 0;
#endif
#endif
  i=j=0;
  while(i<HWADDR_NBYTES){
    unsigned char c=if_mac[i++];  // tu nie ma znaczenia czy if_mac jest wskaznikiem czy buforem
    char k=c>>4;
    buf[j++]=k>9?'A'-10+k:'0'+k;
    k=c&15;
    buf[j++]=k>9?'A'-10+k:'0'+k;
    buf[j++]=j<HWADDR_LEN-1?':':0;
  }
  return buf;
}

4 komentarzy

hehe ups ;-)
Jasne, że nie ;]

a czytales w ogole tytul ? :>

Czy mi się wydaje, czy to zadziała tylko pod *niksem?