Linux下獲取eth網卡MAC地址的代碼

jopen 9年前發布 | 4K 次閱讀 C/C++

因開發需要獲取有線網卡的MAC地址,發現網上獲取的方法多數只能獲取聯網網卡的MAC地址,因此重寫了下Ubuntu 10下測試通過。 下面代碼無論網卡是否連線,都可以獲取MAC地址,稍作修改,可以輸出系統所有的網卡硬件MAC地址,無論是否已經聯網。

getmac.c

/*

  • getmac.c
  • Created on: 2010-11-4
  • Author: carl */

include <stdio.h>

include <fcntl.h>

include <stdlib.h>

include <string.h>

include <unistd.h>

include <sys/ioctl.h>

include <sys/types.h>

include <sys/socket.h>

include <netinet/in.h>

include <linux/if.h>

define IFNAMSIZ 16

// data structs to store interface name list char ifname_buf[2048]; char *ifnames = ifname_buf; int count = 0;

void add_interface_name(const char name) { int i; for (i=0;i<count;i++) { if (!strcmp(ifnames+iIFNAMSIZ, name)) return; } strncpy(ifnames+(count++)*IFNAMSIZ, name, IFNAMSIZ-1); }

char get_name(char name, char p) { while (isspace(p)) p++; while (p) { if (isspace(p)) break; if (p == ':') { / could be an alias / char dot = p, dotname = name; name++ = p++; while (isdigit(p)) name++ = p++; if (p != ':') { / it wasn't, backup / p = dot; name = dotname; } if (p == '\0') return NULL; p++; break; } name++ = p++; } *name++ = '\0'; return p; }

// get /proc/net/dev interface name list into buffer // return 0 if success int get_procnet_list() { FILE *fh; char buf[512]; fh = fopen("/proc/net/dev", "r"); if (!fh) return -1;

fgets(buf, sizeof buf, fh); /* eat title lines */ 
fgets(buf, sizeof buf, fh); 
while (fgets(buf, sizeof buf, fh)) 
{ 
    char name[IFNAMSIZ]; 
    get_name(name, buf); 
    add_interface_name(name); 
} 
fclose(fh); 
return 0; 

}

long mac_addr_sys ( u_char addr) { / implementation for Linux / struct ifreq ifr; struct ifreq IFR; struct ifconf ifc; char buf[1024]; int s, i; int ok = 0;

// clear buffer 
memset(ifname_buf, 0, sizeof(ifname_buf)); 

s = socket(AF_INET, SOCK_DGRAM, 0); 
if (s==-1) { 
    return -1; 
} 

ifc.ifc_len = sizeof(buf); 
ifc.ifc_buf = buf; 
ioctl(s, SIOCGIFCONF, &ifc); 

IFR = ifc.ifc_req; 
// put the ioctl interface names in the list 
for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; IFR++) { 
        add_interface_name(IFR->ifr_name); 
} 
// put the /proc/net/dev interface names in the list 
if (get_procnet_list()) 
    return -1; 

// get the first mac address of eth* device hardware address 
for (i = 0; i < count; i++) { 
    strcpy(ifr.ifr_name, ifnames + i*IFNAMSIZ); 
    if (!strncmp(ifr.ifr_name, "eth", 3)) 
        if (ioctl(s, SIOCGIFFLAGS, &ifr) == 0) { 
            if (! (ifr.ifr_flags & IFF_LOOPBACK)) { 
                if (ioctl(s, SIOCGIFHWADDR, &ifr) == 0) { 
                    char *p = (char *)ifr.ifr_hwaddr.sa_data; 
                    if (!*((int *)p) && !*((int *)(p+2)) ) 
                        continue; 
                    // if not 00:00:00:00:00:00, yes, we get the real mac addr 
                    ok = 1; 
                    break; 
                } 
            } 
        } 
} 

close(s); 
if (ok) { 
    bcopy( ifr.ifr_hwaddr.sa_data, addr, 6); 
} 
else { 
    return -1; 
} 
return 0; 

}

/***/ /*

  • Main (only for testing) */ int main( int argc, char **argv) { long stat; int i; u_char addr[6];

    stat = mac_addr_sys( addr); if (0 == stat) {

     printf( "MAC address = "); 
     for (i=0; i<6; ++i) { 
         printf("%2.2x", addr[i]); 
         if (i<5) 
             printf(":"); 
     } 
     printf( "\n"); 
    

    } else {

     fprintf( stderr, "can't get MAC address\n"); 
     exit( 1); 
    

    } return 0; } </pre>

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!