Harvesting MAC addresses

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.




This entry was posted in Inventory project. Bookmark the permalink.