rtnetlink ile Fiziksel Ethernet Linklerini Filtreleme

Bir rtnetlink RTM_GETLINK dump’ı sistemdeki her ağ arayüzünü döndürür: loopback, fiziksel NIC’ler, bridge’ler, veth çiftleri, VLAN’lar, WireGuard tünelleri, TUN cihazları vb. Yalnızca fiziksel kablolu Ethernet adaptörlerini istiyorsan üç kategoriyi filtrelemen gerekir:

  1. Ethernet olmayan link türleri — loopback (ARPHRD_LOOPBACK), WireGuard/TUN (ARPHRD_NONE) vb.
  2. Sanal Ethernet arayüzleri — bridge’ler, veth’ler, VLAN’lar, bond’lar, macvlan vb. Bunların hepsi ifi_type == ARPHRD_ETHER bildirir ama türünü tanımlayan bir IFLA_LINKINFO attribute’u taşır.
  3. Kablosuz arayüzler — Wi-Fi adaptörleri de ARPHRD_ETHER bildirir ve IFLA_LINKINFO taşımaz, bu yüzden yalnızca netlink ile kablolu Ethernet’ten ayırt edilemez.

Bu yazı, üç filtreyi de uygulayan ve yalnızca fiziksel kablolu Ethernet linklerini yazdıran kompakt bir C++ programı gösterir.

Üç filtre

Filtre 1: ifi_type == ARPHRD_ETHER

struct ifinfomsg içindeki ifi_type alanı ARP donanım türünü tutar. Kablolu Ethernet, Wi-Fi, bridge’ler ve veth’lerin hepsi ARPHRD_ETHER (1) bildirir. Loopback 772 (ARPHRD_LOOPBACK), tünel arayüzleri (WireGuard, TUN) 65534 (ARPHRD_NONE) bildirir. Bu filtre, L2’de Ethernet çerçeveli olmayan her şeyi kaldırır.

Filtre 2: IFLA_LINKINFO yok

Sanal Ethernet arayüzleri — bridge’ler (Kind: bridge), veth’ler (Kind: veth), VLAN’lar (Kind: vlan), bond’lar (Kind: bond), macvlan vb. — hepsi içinde IFLA_INFO_KIND bulunan iç içe IFLA_LINKINFO attribute’unu taşır. Fiziksel arayüzler (kablolu ve kablosuz) hiç IFLA_LINKINFO taşımaz.

Yani: attribute listesinde IFLA_LINKINFO varsa, arayüz sanaldır ve atlanmalıdır.

Filtre 3: /sys/class/net/<name>/wireless yok

Wi-Fi adaptörleri IFLA_LINKINFO olmayan fiziksel cihazlardır, bu yüzden filtre 1 ve 2’yi geçer. Kernel, rtnetlink link dump’ında bir “kablosuz mu” flag’i sunmaz (IFLA_WIRELESS attribute’u yalnızca wireless extension event’lerinde gönderilir, dump yanıtlarında değil).

Wi-Fi’ı tespit etmenin güvenilir yolu /sys/class/net/<name>/wireless dizininin varlığını kontrol etmektir — kernel bu dizini yalnızca kablosuz arayüzler için oluşturur. Aday arayüz başına bir stat() çağrısı gerektirir, tipik olarak yalnızca birkaç tane olduğundan ihmal edilebilir.

Program

Not: <linux/if_arp.h> ve <net/if.h> ikisi de IFF_* flag’lerini tanımlar ve birlikte include edilirse çakışır. Bu program yalnızca <linux/if_arp.h>‘dan ARPHRD_ETHER‘e ihtiyaç duyar, bu yüzden <net/if.h> atlanmıştır. IFF_* flag sabitlerine ihtiyacın varsa yalnızca <net/if.h>‘ı include et ve ARPHRD_ETHER‘i 1 olarak sabit yaz.

Derleme ve çalıştırma

Özel yetki gerekmez.

Örnek çıktı

Loopback, Wi-Fi, birkaç Docker bridge’i ve veth çifti, WireGuard tünelleri ve tek bir USB Ethernet adaptörü olan bir host’ta, program yalnızca fiziksel kablolu Ethernet linkini yazdırır:

Karşılaştırma için, aynı host’un tam rtnetlink dump’ında 30+ arayüz var — hepsi yukarıdaki üç kontrolle filtrelenir.

Neden sadece arayüz adını kontrol etmiyoruz?

Arayüz adları kuralları takip eder (enX = kablolu Ethernet, wlX = Wi-Fi, brX = bridge, vethX = veth çifti), ama bunlar kuraldır, garanti değil. USB Ethernet adaptörleri varsayılan olarak enx<MAC> kullanır ama udev kuralları veya ip link set name ile yeniden adlandırılabilir. IFLA_LINKINFO + sysfs yaklaşımı, kullanıcının verdiği adı değil kernel’in arayüz hakkında bildirdiklerini denetlediği için yeniden adlandırmaya karşı dayanıklıdır.

Ayrıca bu filtrenin türetildiği tam link-dump programı için rtnetlink API ile tüm ağ linklerini listeleme, tamamlayıcı VLAN filtresi için rtnetlink ile VLAN arayüzlerini filtreleme ve attribute-walking deyimi için rtnetlink rtattr attribute’larını iterate etme yazılarına bak.


Check out similar posts by category: C/C++ Linux