36

Is it possible to read the MAC address from the NIC directly? I have the code below but it just reads from the layer above but not the card itself.

I'm trying to figure out how to find the original MAC address of an Ethernet NIC on my Linux box. I understand how to find the current MAC address using ifconfig.

But the address can be changed, say by using

ifconfig eth0 hw ether uu:vv:ww:yy:xx:zz

or setting it "permanently" using /etc/sysconfig/network-scripts/ifcfg-eth0.

How do I find the original MAC address? There must be a way to find it, because it is still burned permanently into the card, but I can't find a tool to read the burned in address.

Is there any utility or command for that?

I suppose it should be possible to write C code for it, below code gives my current MAC but not the original 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;
}

OS: Red Hat Linux, 2.6.18.8-1

Matthias Braun
  • 32,039
  • 22
  • 142
  • 171
Jatin Bodarya
  • 1,425
  • 2
  • 20
  • 32
  • 2
    Just because it is burned there, does not mean it HAS to be available. I don't know how linux and the cards work, but it would be entirely plausible if the MAC was only restored on a power cycle when the cards' firmware does initialization. – Prof. Falken Feb 19 '13 at 10:53
  • I just want to UP my machine with SPOOFED MAC and I can do it successfully . but during that I want my original MAC for my application. that is my issue. – Jatin Bodarya Feb 19 '13 at 11:09
  • I think @AmigableClarkKant is suggesting that a full power cycle might make the NIC initialize from firmware. Don't just restart; shutdown, wait, power on. That might restart the NIC with its original MAC address. Then you could retrieve and store the original MAC address *before* you change it at run time. – Mike Sherrill 'Cat Recall' Feb 19 '13 at 11:19
  • ohh.... I have no Idea How to do that Pragmatically.. There is no other way that I can get it whenever I want in my application... using C code (without storing it somewhere) – Jatin Bodarya Feb 19 '13 at 11:27
  • It is a matter of "how do you get that information", assuming it is available. All the drivers for the network cards will know how to do this, but like I describe below, the information is read then stored, and if that gets overwritten later, then that's it - gone. You could add some code to each driver, but that would be a lot of work, and almost certain not to get into the Linux kernel, so you'd forever carry a patch for every network driver available - that would be rather a lot of effort to maintain... – Mats Petersson Feb 19 '13 at 11:41

7 Answers7

65

Certainly in ethtool you can just print the address:

 -P --show-permaddr
    Queries the specified network device for permanent hardware address.

e.g.

ethtool -P eth0

produces

Permanent address: 94:de:80:6a:21:25

Matthias Braun
  • 32,039
  • 22
  • 142
  • 171
Jay M
  • 3,736
  • 1
  • 24
  • 33
  • 4
    Best answer; to see the C code, search `do_permaddr` in [`ethtool.c`](http://git.kernel.org/cgit/network/ethtool/ethtool.git/tree/ethtool.c). – bufh Nov 03 '15 at 11:12
  • After new naming schemes were released: **ethtool -P wlp1s0** works as a replacement if you are connected to wifi – ypahalajani Jan 21 '17 at 00:16
  • In my Debian 9 system, I had to first install ethtool by running `sudo apt install ethtool`, and then run `ethtool -P eth0` as root. – HelloWorld101 Sep 03 '18 at 08:19
18

Try cat /sys/class/net/eth0/address or cat /sys/class/net/em1/address if using Fedora. It should work.

The original answer is here: Notes of a Systems Admin

tver3305
  • 8,224
  • 2
  • 21
  • 23
9

The only way to find the original MAC address is to use the same method the network card driver does - unfortunately, I don't believe there is a generic way to tell the driver to provide its MAC address "as provided by the hardware". Of course, there are cases where there isn't a hardware network card for that particular interface - virtual network drivers for virtualization and when using bridges and software switches for example.

And of course, the hardware may be such that you can't actually read the "original" MAC address when it has been overwritten by software, because there is only one set of registers for the MAC address itself.

I had a quick look at the pcnet32.c drivers (because it's one of the models of network card that I have a rough idea how it works and where the different registers are, etc, so I can see what it does). As far as I can see, it supports no method of actually asking "what is your PROM Ethernet address" - the MAC address is read out during the "probe1" section of the module initialization, and stored away. No further access to those hardware registers is made.

Matthias Braun
  • 32,039
  • 22
  • 142
  • 171
Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • So the only way is to patch all network drivers. But since that is both *insane* and he has not sudo, it's a no go. Short answer: impossible. – Prof. Falken Feb 19 '13 at 14:48
  • Even patching all the network drivers will only work for REAL HARDWARE network cards. Which isn't necessarily what your "machine" has if it's a virtual machine, or if it's got some more exotic types of network software processing that uses a software network interface to do switching/bridging/etc. – Mats Petersson Feb 19 '13 at 14:50
  • Not to mention that some hardware does not have a default MAC address at all :) –  Feb 28 '13 at 18:59
7

Well, the old ethernet address remains in the first bytes of the card eeprom (at least for some types of cards), so it is possible to extract it using ethtool

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

where tt:uu:ww:xx:yy:zz is old mac address

begemotv2718
  • 868
  • 6
  • 14
  • 1
    Of course, that assumes you have physical access to the network card. When I tried the same thing on my XEN-based Fedora 17 [so related to RedHat Linux], even in the privileged domain, it says "No EEPROM data available". – Mats Petersson Feb 19 '13 at 11:26
  • this tool is not useful for general case its not working for me also and my another issue is I can not use "sudo"...!! – Jatin Bodarya Feb 19 '13 at 11:42
  • I have 3 network cards in my Fedora system, but this method did not work for any of them - one cannot retrieve EEPROM, others can retrieve it, but strings do not match – mvp Feb 19 '13 at 11:44
  • 2
    Some cards doesn't have it in the first bytes of eeprom, I tested on another machine, there I had ethernet address somewhere at offset 0x0233, so this indeed is not universal. It is correct that some cards does not support eeprom dump at all. – begemotv2718 Feb 19 '13 at 11:52
  • ***`Cannot get EEPROM data: Operation not supported...`*** from a wifi adapter on a [LeMaker HiKey](http://www.amazon.com/gp/product/B019O3QTSA) (inexpensive ARM64 test device). – jww Jan 08 '16 at 14:07
6

This may not be the programmatic way, but why not search dmesg. All of my machines' NICs spit out the MAC address at detection time.

Try something like this:

dmesg|grep eth0

Different NICs display the MAC address differently, but the log will always contain the kernel given name of the adapter (in most cases eth0 or wlan0).

Youssef Bouhjira
  • 1,599
  • 2
  • 22
  • 38
user3462738
  • 69
  • 1
  • 1
  • 2
    My NIC doesn't even have an interface name like `eth0`. The kernel isn't managing it; Intel DPDK is. How do I get the MAC address then? – sudo Feb 03 '17 at 08:53
0

In Ubuntu 18.4 LTS
First you need to find the network interface names on the computer by command

ls /sys/class/net

My output is

docker0  enp0s31f6  lo

Now you can use the command as discussed above, dont forget the sudo

sudo ethtool -P enp0s31f6
Dr. Mian
  • 3,334
  • 10
  • 45
  • 69
-1

This command lists all the ethernet devices and original HW addresses.

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