Using getifaddrs
, we can iterate over all the available network interfaces on a machine. For this question, I'm only concerned with layer 2 (link layer) interfaces - i.e. interfaces of the AF_PACKET
family.
When we are iterating over all the interfaces returned from getifaddrs
, and we find a struct ifaddrs
instance whose ifa_addr->sa_family
field is AF_PACKET
, it seems we still need further information about what type of layer 2 interface we are dealing with.
We can rule out loopback interfaces and point-to-point interfaces by checking the ifa_flags
field. But apart from that, how can we tell if a particular AF_PACKET
interface is Ethernet, or something else? Presumably, it could also be some other Layer 2 technology, like WiFi, token-ring, or Bluetooth. So how can we tell if it is Ethernet or something else?
Reading the documentation for struct sockaddr_ll
, it appears there is a field sll_protocol
that contains "the standard ethernet protocol type in network byte order". This confuses me a bit, because now I'm unsure whether sockaddr_ll
is supposed to only be used for Ethernet, or whether it's supposed to be used as a generic link layer socket object. The fact that the documentation says that sll_protocol
contains the standard ethernet protocol indicates to me that sockaddr_ll
is supposed to only be used for Ethernet. But yet the sll_addr
field seems to be more generic (it can contain a length up to 8 bytes, instead of just a 6 byte MAC address).
I'm also unsure if the family AF_PACKET
itself is what is supposed to tell me that the physical media must be Ethernet.
The only other clue I can find on how to do this comes from http://www.microhowto.info/howto/get_the_mac_address_of_an_ethernet_interface_in_c_using_siocgifhwaddr.html. This seems to imply that by using the older struct ifreq
and ioctl
interface, along with SIOCGIFHWADDR
, you can definitely tell if a particular interface is Ethernet by checking the sa_family
field of the ifr_hwaddr
field in the ifreq
struct. If the device is an Ethernet device, the sa_family
field should be set to ARPHRD_ETHER
.
But I'm confused as to why this is not consistent with getifaddrs
, where the ifa_addr->sa_family
field is simply AF_PACKET
for layer 2 Ethernet interfaces. It seems this newer API (getifaddrs
) doesn't provide any way to distinguish if a particular network interface is actually Ethernet, versus some other Layer 2 technology like WIFI.
So what is the best way determine if a particular network interface is Ethernet (as opposed to some other Layer 2 technology)?