2012-01-27 34 views
7

używam następujący kod, aby pobrać wszystkie adresy MAC na bieżącym komputerze:C/C++ Linux MAC Address wszystkich interfejsów

ifreq ifr; 
ifconf ifc; 
char buf[1024]; 

int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); 
if (sock == -1) { ... }; 

ifc.ifc_len = sizeof(buf); 
ifc.ifc_buf = buf; 
if (ioctl(sock, SIOCGIFCONF, &ifc) == -1) { ... } 

ifreq *it = ifc.ifc_req; 
const ifreq* const end = it + (ifc.ifc_len/sizeof(ifreq)); 

for (; it != end; ++it) { 
    strcpy(ifr.ifr_name, it->ifr_name); 
    if (ioctl(sock, SIOCGIFFLAGS, &ifr) == 0) { 
     if (!(ifr.ifr_flags & IFF_LOOPBACK)) { 
      if (ioctl(sock, SIOCGIFHWADDR, &ifr) == 0) { 
       unsigned char mac_address[6]; 
       memcpy(mac_address, ifr.ifr_hwaddr.sa_data, 6); 
       ... 
      } 
     } 
    } 
    else { ... } 
} 

Uruchamiając proste polecenie powłoki ifconfig widzę lo, eth0 i wlan0. Chciałbym pobrać adresy MAC dla eth0 i wlan0 przez mój kod C/C++. Ale tylko wlan0 jest zwracany - eth0 brakuje (mam ifr_names lo, lo, wlan0). Prawdopodobnie dlatego, że eth0 nie jest aktywny (kabel sieciowy nie jest podłączony, a kabel jest zwrócony). Czy mogę jakoś zmienić to polecenie ioctl (SIOCGIFCONF), aby pobrać eth0, nawet jeśli jest "wyłączone"?

mogę dostać jego adres HW za pomocą bezpośrednio

struct ifreq s; 
    int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); 

    strcpy(s.ifr_name, "eth0"); 
    if (0 == ioctl(fd, SIOCGIFHWADDR, &s)) { ... } 

ale co jeśli nazwa nie byłaby eth0 ale coś innego (eth1, em0, ...)? Chciałbym je wszystkie zdobyć. Dzięki za pomoc.

Odpowiedz

9

Powinieneś przestać używać narzędzi sieciowych i archaicznego interfejsu ioctl i zacząć korzystać z nowoczesnych interfejsów Netlink/sysfs. Nie masz mniej niż 5 możliwości:

  • napisać własny kod Netlink-relacje
  • własny kod NL, w połączeniu z wykorzystaniem libmnl (-> patrz rtnl-link-dump w Examples
  • lub wykorzystać autonomiczne bibliotekami jak libnl3
  • parse wyjściu tekstu ip -o link (-o jest dostać wyjście oznaczało dla analizowania tekstu, w przeciwieństwie do ifconfig)
  • lub użyj sysfs i tylko lo ok w /sys/class/net/eth0/address
0

Może nie tak elegancko, ale można przechwycić wyniki z ifconfig, ponieważ wygląda na to, że ma dokładnie to, czego szukasz.

+0

dzięki, że zawsze jest rozwiązanie, ale wolałbym użyć jakieś rozwiązanie C, analizowania wyników ifconfig może być problematyczne, format może być różny w różnych wersjach Linux, itd – user1173626

1

można znaleźć rozwiązanie tutaj: Get mac address given a specific interface

można po prostu pominąć określoną część interfejsu.

+0

Dzięki, ale jestem nie jestem pewien, czy rozumiem, co masz na myśli. W twoim przykładzie kodu wszystko polega na pytaniu o parametry interfejsu o nazwie argv [1] - które może być na przykład eth0 jak w moim drugim fragmencie kodu. W porządku. Ale muszę wymienić wszystkie interfejsy. Pomijając "konkretną" część, jak sugerujesz, co zostanie? Muszę uzyskać listę interfejsów, o szczegóły zapytam (MAC), czy to prawda? O ile rozumiem, to właśnie robię, dzwoniąc do SIOCGIFCONF. Ale eth0 nie znajduje się na liście. – user1173626

+0

Co powiesz na połączenie tych dwóch odpowiedzi: przeanalizuj wyniki ifconfig TYLKO dla nazw (uważam, że byłoby to dość agnostyczne) i zastosuj to podejście, aby wyszukać adres MAC dla każdego znalezionego nazwiska. –

+0

Albo pobierz źródło dla ifconfig i zobacz, jak znajduje te nazwy. –