Используя getifaddrs
, мы можем перебирать все доступные сетевые интерфейсы на машине. В этом вопросе меня интересуют только интерфейсы уровня 2 (канального уровня) - то есть интерфейсы семейства AF_PACKET
.
Когда мы выполняем итерацию по всем интерфейсам, возвращаемым из getifaddrs
, и находим экземпляр struct ifaddrs
, чье поле ifa_addr->sa_family
равно AF_PACKET
, кажется, нам все еще нужна дополнительная информация о том, какой тип интерфейса уровня 2 мы имеют дело.
Мы можем исключить петлевые интерфейсы и двухточечные интерфейсы, проверив поле ifa_flags
. Но кроме этого, как мы можем определить, является ли конкретный интерфейс AF_PACKET
Ethernet или чем-то еще? Предположительно, это также может быть какая-то другая технология уровня 2, например, WiFi, Token-Ring или Bluetooth. Итак, как мы можем определить, является ли это Ethernet или чем-то еще?
Считая документацию для struct sockaddr_ll
, появляется поле sll_protocol
, которое содержит «стандартный тип протокола Ethernet в сетевом порядке байтов». Это немного смущает меня, потому что теперь я не уверен, должен ли sockaddr_ll
использоваться только для Ethernet, или он должен использоваться в качестве универсального объекта сокета канального уровня. Тот факт, что в документации сказано, что sll_protocol
содержит стандартный протокол ethernet , указывает мне, что sockaddr_ll
предполагается использовать только для Ethernet. Но все же поле sll_addr
кажется более общим (оно может содержать длину до 8 байт вместо 6-байтового MAC-адреса).
Я также не уверен, что именно семья AF_PACKET
должна сказать мне, что физический носитель должен быть Ethernet.
Единственный другой ключ, который я могу найти о том, как это сделать, прибывает из http://www.microhowto.info/howto/get_the_mac_address_of_an_ethernet_interface_in_c_using_siocgifhwaddr.html. Это, кажется, подразумевает, что, используя более старый интерфейс struct ifreq
и ioctl
, наряду с SIOCGIFHWADDR
, вы определенно можете скажите, является ли конкретный интерфейс Ethernet, проверив поле sa_family
поля ifr_hwaddr
в структуре ifreq
. Если устройство является устройством Ethernet, поле sa_family
должно быть установлено на ARPHRD_ETHER
.
Но я не совсем понимаю, почему это не согласуется с getifaddrs
, где поле ifa_addr->sa_family
просто AF_PACKET
для интерфейсов Ethernet уровня 2. Кажется, что этот более новый API (getifaddrs
) не предоставляет никакого способа отличить, является ли конкретный сетевой интерфейс фактически Ethernet, по сравнению с какой-либо другой технологией уровня 2, такой как WIFI.
Итак, как лучше всего определить, является ли конкретный сетевой интерфейс Ethernet (в отличие от какой-либо другой технологии уровня 2)?