【问题标题】:Finding original MAC address from hardware itself从硬件本身查找原始 MAC 地址
【发布时间】:2013-02-19 10:45:08
【问题描述】:

操作系统:REDHAT LINUX Linux 管理:2.6.18.8-1 #

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

我试图弄清楚如何在我的 linux 机器上找到以太网 NIC 的原始 MAC 地址。我了解如何使用 ifconfig 查找当前 MAC 地址,但如果地址已更改,请使用 'ifconfig eth0 hw ether uu:vv:ww:yy:xx:zz',或者我使用vi /etc/sysconfig/network-scripts/ifcfg-eth0.this 文件将它设置为“永久”...我也可以在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;
}

【问题讨论】:

  • 仅仅因为它在那里被烧毁,并不意味着它必须可用。我不知道 linux 和卡是如何工作的,但如果 MAC 仅在卡固件初始化时在电源循环中恢复,那将是完全合理的。
  • 我只想用 SPOOFED MAC UP 我的机器,我可以成功地做到这一点。但在此期间,我想要我的原始 MAC 用于我的应用程序。那是我的问题。
  • 我认为@AmigableClarkKant 暗示完整的电源循环可能会使 NIC 从固件初始化。不要只是重新启动;关机,等待,开机。这可能会使用其原始 MAC 地址重新启动 NIC。然后,您可以在运行时更改它之前检索并存储原始 MAC 地址。
  • ohh.... 我不知道如何务实地做到这一点.. 没有其他方法可以在我的应用程序中随时获取它...使用 C 代码(不存储它某处)
  • 这是一个“你如何获得该信息”的问题,假设它是可用的。网卡的所有驱动程序都知道如何执行此操作,但就像我在下面描述的那样,信息被读取然后存储,如果稍后被覆盖,那就是它 - 消失了。您可以向每个驱动程序添加一些代码,但这将是很多工作,并且几乎可以肯定不会进入 Linux 内核,因此您将永远为每个可用的网络驱动程序携带一个补丁 - 这将是相当多的努力维护...

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


【解决方案1】:

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

例如

ethtool -P eth0

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

【讨论】:

  • 最佳答案;要查看 C 代码,请在 ethtool.c 中搜索 do_permaddr
  • 新命名方案发布后:ethtool -P wlp1s0 如果您连接到 wifi,则可以替代
  • 在我的 Debian 9 系统中,我必须先通过运行 sudo apt install ethtool 安装 ethtool,然后以 root 身份运行 ethtool -P eth0
【解决方案2】:

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

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

【讨论】:

  • 那不是永久/原始 mac(如果已更改)。它是临时或当前的 mac 地址。
【解决方案3】:

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

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

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

【讨论】:

  • 所以唯一的办法就是给所有网络驱动打补丁。但由于这既是疯狂,而且他没有sudo,所以这是不行的。简短的回答:不可能。
  • 即使修补所有网络驱动程序也只适用于真正的硬件网卡。如果它是虚拟机,或者它有一些更奇特的网络软件处理类型,使用软件网络接口进行切换/桥接/等,则不一定是你的“机器”所具有的。
  • 更不用说有些硬件根本没有默认MAC地址:)
【解决方案4】:

好吧,旧的以太网地址保留在卡 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 地址

【讨论】:

  • 当然,前提是您可以物理访问网卡。当我在基于 XEN 的 Fedora 17 [与 RedHat Linux 如此相关] 上尝试相同的操作时,即使在特权域中,它也会显示“没有可用的 EEPROM 数据”。
  • 这个工具对一般情况没有用,它对我也不起作用,我的另一个问题是我不能使用“sudo”......!!
  • 我的 Fedora 系统中有 3 个网卡,但是这种方法对其中任何一个都不起作用 - 一个无法检索 EEPROM,其他人可以检索它,但字符串不匹配
  • 有些卡在eeprom的第一个字节中没有它,我在另一台机器上测试,我在偏移量0x0233的某个地方有以太网地址,所以这确实不是通用的。有些卡根本不支持eeprom dump是对的。
  • Cannot get EEPROM data: Operation not supported...来自LeMaker HiKey(廉价的ARM64测试设备)上的wifi适配器。
【解决方案5】:

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

试试这样的:

dmesg|grep eth0

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

【讨论】:

  • 我的网卡甚至没有像eth0 这样的接口名称。内核没有管理它;英特尔 DPDK 是。那我如何获取 MAC 地址呢?
【解决方案6】:

在 Ubuntu 18.4 LTS 中
首先需要通过命令找到电脑上的网络接口名称

ls /sys/class/net

我的输出是

docker0  enp0s31f6  lo

现在你可以使用上面讨论的命令了,别忘了sudo

sudo ethtool -P enp0s31f6

【讨论】:

    【解决方案7】:

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

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

    【讨论】:

      猜你喜欢
      • 2012-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-23
      • 2012-03-21
      • 1970-01-01
      • 1970-01-01
      • 2014-09-19
      相关资源
      最近更新 更多