Linux – Change MAC address of network interface on lower level

linuxmac addressnetworking

I know that I can change a network interface's MAC address by bringing the interface down, using a command like ifconfig eth0 hw ether 00:11:22:33:44:55 or ip link set eth0 address 00:11:22:33:44:55 and then bringing the interface up again. A command like ip link show eth0 then confirms that the change was successful.

But I recently discovered the files in /sys/class/net (originally from this answer): each one is a symbolic link to a directory containing files with information about the interface as documented here For example, on my machine, the ethernet interface is enp3s0 (I have no idea why it has such a strange name), and /sys/class/net/enp3s0 links to /sys/devices/pci0000:00/0000:00:1c.2/0000:03:00.0/net/enp3s0.

In this directory, I then found the file address which is just a text file containing the MAC address of the interface. But when I attempt to change the address using one of the commands above, the address file stays the same, so apparently, the commands do not change the MAC address on the lowest level. It is also not possible to change this file in any manner, not even the superuser has permission to do this.

So now, just out of curiosity: Is it possible to change the MAC address of a network interface on this level?

Best Answer

Background

/proc and /sys filesystems are just a view of kernel structures, both filesystems reside in memory. Although both filesystems are writable (well, some of the files in there are writable) it is unwise to assume that they behave the same way as a real filesystems.

Operations that allow you to write into a file inside /proc or /sys end as hooks and then as function calls. For example:

# echo 3 > /proc/sys/vm/drop_caches

Does not really write to that file, it calls a userspace kernel function.

If a function is not defined for a certain write you will get:

write error: Input/output error

That is because it does not make sense to write to that file. It is not that different from writing to the character device of a USB device that has no driver associated to. The kernel does not know what to do.

There is no function defined for writes against /sys/class/net/enp3s0/address, therefore that is not a viable route to change the MAC address of that interface.

Can I change the MAC address without calling ifconfig or ip link set ?

Yes, you can.

If you look at the code for iproute2 you will find a lot of argument parsing and a call to rtnl_talk. It looks as follows (this is from the ip/iplink.c file):

/* lot of argument parsing and `req` setting */

if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
        exit(2);

return 0;

req.n in there is the MAC address being passed to rnetlink function rtnl_talk (man rnetlink is relevant here). If you write a program that perform this call it will fire a system call and update the MAC address. Yet, then you will be doing exactly the same what ip link set does.

Related Question