从硬件本身查找原始MAC地址

时间:2013-02-19 10:45:09

标签: linux sockets linux-kernel linux-device-driver mac-address

Os:REDHAT LINUX Linux管理:2.6.18.8-1#

这是否可以直接从NIC读取MAC地址?我有下面的代码,但它只是从上面的图层读取,但不是卡本身!!!

我正在试图弄清楚如何在我的linux机箱上找到以太网网卡的原始MAC地址。我理解如何使用ifconfig查找当前的MAC地址,但如果地址已更改,请使用 'ifconfig eth0 hw ether uu:vv:ww:yy:xx:zz',或者我使用vi /etc/sysconfig/network-scripts/ifcfg-eth0设置“永久”。此文件...我也可以UP成功REBOOT它。我怎么找原件?必须有一种方法来找到它,因为它仍然永久地刻录到卡中,但我找不到一个工具来读取刻录的地址。 它有什么用途或命令吗? 我想为它编写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;
}

7 个答案:

答案 0 :(得分:48)

当然在ethtool 3.1中你可以打印地址: ethtool -P | --show-permaddr DEVNAME显示永久硬件地址

e.g。

ethtool -P eth0

永久地址:94:de:80:6a:21:25

答案 1 :(得分:15)

如果使用Fedora,请尝试cat /sys/class/net/eth0/addresscat /sys/class/net/em1/address。它应该工作。

原始答案在这里:Notes of a Systems Admin

答案 2 :(得分:8)

找到原始MAC地址的唯一方法是使用与网卡驱动程序相同的方法 - 不幸的是,我不相信有一种通用的方法告诉驱动程序提供它的MAC地址“由硬件”。当然,在某些情况下,没有针对该特定接口的硬件网卡 - 虚拟化的虚拟网络驱动程序以及使用网桥和软件交换机时的情况。

当然,硬件可能是这样的,当它被软件覆盖时你实际上无法读取“原始”MAC地址,因为MAC地址本身只有一组寄存器。

我快速浏览了一下pcnet32.c驱动程序(因为它是网卡的一种模型,我大致了解它是如何工作的以及不同寄存器的位置等,所以我可以看到它的作用) 。据我所知,它不支持实际询问“你的PROM以太网地址是什么”的方法 - 在模块初始化的“probe1”部分读出MAC地址,然后存储起来。无法进一步访问这些硬件寄存器。

答案 3 :(得分: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地址

答案 4 :(得分:5)

这可能不是编程方式,但为什么不搜索dmesg。我的所有机器的NIC都会在检测时吐出MAC地址。

尝试这样的事情:

dmesg|grep eth0

不同的NIC以不同的方式显示MAC地址,但日志将始终包含给定适配器名称的内核(在大多数情况下为eth0wlan0)。

答案 5 :(得分:0)

在Ubuntu 18.4 LTS中
首先,您需要通过命令在计算机上找到网络接口名称

ls /sys/class/net

我的输出是

docker0  enp0s31f6  lo

现在您可以使用上面讨论的命令,不要忘记sudo

sudo ethtool -P enp0s31f6

答案 6 :(得分:-1)

此命令列出所有以太网设备和原始HW地址。

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