2013-02-19 22 views
23

鋨:REDHAT LINUX的Linux管理:2.6.18.8-1#從硬件本身查找原始MAC地址

這是可以直接讀取MAC地址形式網卡?我有下面的代碼,但它只是從上面的層讀取,但不是卡本身!

我想弄清楚如何在我的linux機器上找到以太網網卡的原始MAC地址。我知道如何使用ifconfig找到當前的MAC地址,但是如果地址已被改變,比如說使用 'ifconfig eth0 hw ether uu:vv:ww:yy:xx:zz',或者我使用vi /etc/sysconfig/network-scripts/ifcfg-eth0這個文件設置了「永久」。我可以成功地在REBOOT中也得到UP。我如何找到原件?必須有辦法找到它,因爲它仍然被永久性地燒入卡片中,但我找不到一個工具來讀取刻錄地址。 是否有任何實用工具或命令? 我想爲它編寫C代碼。但在上述情況下不知道如何做到這一點。

**下面的代碼給我當前 MAC而不是原來的MAC

#include <stdio.h>    /* Standard I/O */ 
#include <stdlib.h>    /* Standard Library */ 
#include <errno.h>    /* Error number and related */ 


#define ENUMS 
#include <sys/socket.h> 
#include <net/route.h> 
#include <net/if.h> 
#include <features.h>   /* for the glibc version number */ 
#if __GLIBC__ >= 2 && __GLIBC_MINOR >= 1 
#include <netpacket/packet.h> 
#include <net/ethernet.h>  /* the L2 protocols */ 
#else 
#include <asm/types.h> 
#include <linux/if_packet.h> 
#include <linux/if_ether.h>  /* The L2 protocols */ 
#endif 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <sys/un.h> 
#include <sys/ioctl.h> 
#include <netdb.h> 


int main(int argc, char * argv[]){ 

unsigned char mac[IFHWADDRLEN]; 
int i; 
    get_local_hwaddr(argv[1], mac); 
    for(i = 0; i < IFHWADDRLEN; i++){ 
     printf("%02X:", (unsigned int)(mac[i])); 
    } 

} 


int get_local_hwaddr(const char *ifname, unsigned char *mac) 
{ 
    struct ifreq ifr; 
    int fd; 
    int rv;      // return value - error value from df or ioctl call 

    /* determine the local MAC address */ 
    strcpy(ifr.ifr_name, ifname); 
    fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); 
    if (fd < 0) 
     rv = fd; 
    else { 
     rv = ioctl(fd, SIOCGIFHWADDR, &ifr); 
     if (rv >= 0)   /* worked okay */ 
      memcpy(mac, ifr.ifr_hwaddr.sa_data, IFHWADDRLEN); 
    } 

    return rv; 
} 
+2

只因爲它在那裏被燒燬,並不意味着它必須可用。我不知道linux和卡片是如何工作的,但是如果MAC只在電源週期中恢復,那麼當卡片的固件初始化時,這將是完全合理的。 – 2013-02-19 10:53:26

+0

我只想用SPOOFED MAC來啓動我的機器,我可以成功地完成它。但在此期間,我希望我的原始MAC用於我的應用程序。那是我的問題。 – 2013-02-19 11:09:48

+0

我認爲@AmigableClarkKant暗示完整的電源週期可能會使NIC從固件初始化。不要只是重新啓動;關機,等待,開機。這可能會以其原始MAC地址重新啓動NIC。然後,您可以在運行時更改它之前檢索並存儲原始MAC地址*。 – 2013-02-19 11:19:34

回答

7

好了,舊的以太網地址保留在卡的EEPROM的第一個字節(至少對於某些類型的卡)因此可以用來提取它ethtool

bash$ sudo ethtool -e eth1 
Offset  Values 
------  ------ 
0x0000  tt uu ww xx yy zz 79 03 
0x.... 

其中TT:UU:WW:XX:YY:ZZ是舊的MAC地址

+0

好點..... – 2013-02-19 11:22:42

+1

當然,這假定你有物理訪問網卡。當我在基於XEN的Fedora 17 [與RedHat Linux相關]上嘗試同樣的事情時,即使在特權域中,它也表示「沒有EEPROM數據可用」。 – 2013-02-19 11:26:33

+0

這個工具不適用於一般情況下它也不適合我,我的另一個問題是我不能使用「sudo」...... !! – 2013-02-19 11:42:13

7

找到原始MAC地址的唯一方法是使用網卡驅動程序的相同方法 - 不幸的是,我不相信有一種通用的方法來告訴驅動程序提供它的MAC地址「由硬件提供」 。當然,有些情況下,該特定接口沒有硬件網卡 - 例如虛擬化的虛擬網絡驅動程序,以及使用網橋和軟件交換機的情況。

當然,由於MAC地址本身只有一組寄存器,所以當硬件被軟件覆蓋時,硬件可能實際上不能讀取「原始」MAC地址。

我快速瀏覽了pcnet32.c驅動程序(因爲它是網卡的一種型號,我對它的工作原理以及不同寄存器的位置等有一個大概的瞭解,所以我可以看到它的功能)。據我所知,它不支持實際詢問「PROM以太網地址是什麼」的方法 - 在模塊初始化的「probe1」部分讀取MAC地址並將其存儲起來。沒有進一步訪問這些硬件寄存器。

+0

所以唯一的方法是修補所有的網絡驅動程序。但既然這既是*瘋狂*,他也沒有sudo,這是不行的。簡答:不可能。 – 2013-02-19 14:48:37

+0

即使修補所有網絡驅動程序也只適用於REAL HARDWARE網卡。如果你的「機器」是虛擬機,或者它有一些更奇特的網絡軟件處理,它們使用軟件網絡接口來完成交換/橋接等,那麼這不一定就是你的「機器」。 – 2013-02-19 14:50:59

+0

絕對如此。 – 2013-02-19 14:55:31

37

當然,在ethtool的3.1,你可以只打印地址: 的ethtool -P | - 顯示,permaddr DEVNAME顯示永久性硬件地址

例如

ethtool -P eth0 

永久地址:94:DE:80:6A:21:25

+3

最佳答案;要查看C代碼,請在['ethtool.c'](http://git.kernel.org/cgit/network/ethtool/ethtool.git/tree/ethtool.c)中搜索'do_permaddr'。 – bufh 2015-11-03 11:12:54

+0

新命名方案發布後:** ethtool -P wlp1s0 **可作爲替代品,如果您連接到wifi – user2925949 2017-01-21 00:16:36

5

這可能不是編程方式,但爲什麼不搜索dmesg。我的所有機器的網卡在檢測時都會吐出MAC地址。

嘗試是這樣的:

dmesg|grep eth0 

不同的NIC顯示不同的MAC地址,但日誌將始終包含(在大多數情況下eth0wlan0)適配器的內核的名字。

+0

我的網卡甚至沒有像eth0這樣的接口名稱。內核不管理它;英特爾DPDK是。那麼我如何獲得MAC地址? – sudo 2017-02-03 08:53:01

14

如果使用Fedora,請嘗試cat /sys/class/net/eth0/addresscat /sys/class/net/em1/address。它應該工作。

原來答案就在這裏:Notes of a Systems Admin

+2

這不是永久/原始mac(如果它已被更改)。這是臨時或當前的mac地址。 – 2016-10-09 13:13:11

-1

該命令列出了所有的以太網設備和原有的硬件地址。

dmesg | grep eth | grep IRQ | awk {'print "permanent address of " $5 " " $9'} |tr "," " "