The clientreport
script of the current inventory system only reports on one MAC address, and even then simply derives this from the dhclient.mac
resource.
As we intend, in the new inventory system, for the clientreport
script to be the principal route for determining the MAC address of a machine, it must somehow obtain the MAC address directly from the Linux kernel.
There are numerous WWW postings documenting a variety of different ways to enumerate the physical network interfaces of a machine. The quickest route would appear to be to make use of the fact that only physical network interfaces have a file /sys/class/net/{iface}/device
. Each of these interfaces will have a file /sys/class/net/{iface}/address
the contents of which are the MAC address of that interface.
For most machines, that’s the end of the story – but not so on machines with bonded interfaces. When two interfaces are bonded, by necessity one of the pair takes on the MAC address of the other interface – so you end up with two interfaces with the same MAC address. As far as I could see, there is no way to determine the permanent MAC address of the interface whose MAC address has been altered – at least not by reading files in /sys
nor by using the majority of network tools. Even the ioctl()
call SIOCGIFADDR
returns the modified MAC address. Once I discovered the last fact, I almost gave up with finding a solution, assuming that all tools would use either this ioctl()
call, or read /sys
, to determine the MAC address.
However, persistence paid off. I wondered how OCSinventory
solves this problem and took at look at the source code for the OCSinventory
agent. A quick peruse of this code showed that it makes use of ethtool
to determine things like connection speed etc. A peek at the ethtool
man page suggested ethtool --showpermaddr
might do what we wanted. Fully expecting this to return the wrong address, I was pleased to find that it does indeed return the correct permanent address of an interface even if that interface is a slave in a bonded pair. So, how does it do that if ioctl(SIOCGIFADDR)
and /sys
return the wrong answer? It turns out that ethtool
has its own private ioctl()
call called SIOCETHTOOL
.