2011-02-09 6 views
25

Czy istnieje sposób w Linuksie, używając kodu C, aby uzyskać te same informacje, które powróci "ifconfig eth0"? Interesują mnie rzeczy takie jak adres IP, stan łącza i adres MAC.przy użyciu kodu C, aby uzyskać te same informacje, co ifconfig

Oto przykładowe dane wyjściowe z ifconfig:

eth0  Link encap:Ethernet HWaddr 00:0F:20:CF:8B:42 
      inet addr:217.149.127.10 Bcast:217.149.127.63 Mask:255.255.255.192 
      UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 
      RX packets:2472694671 errors:1 dropped:0 overruns:0 frame:0 
      TX packets:44641779 errors:0 dropped:0 overruns:0 carrier:0 
      collisions:0 txqueuelen:1000 
      RX bytes:1761467179 (1679.8 Mb) TX bytes:2870928587 (2737.9 Mb) 
      Interrupt:28 
+0

** 'ifconfig' nie był utrzymywany na Linuksie przez wiele lat. ** Zamiast tego użyj 'ip'. http://serverfault.com/questions/633087/where-is-the-statement-of-deprecation-of-ifconfig-on-linux – mikemaccana

Odpowiedz

67

Jednym ze sposobów na rozwiązanie takich problemów, szczególnie w przypadkach, gdy nie masz źródła, jest strace.

Podaje listę wszystkich wywołań systemowych wykonanych przez każdy program, który przekazujesz, wraz z ich argumentami i wartościami zwracanymi. Jeśli twój program po prostu zrzuca pewne informacje i wychodzi, a nie działa przez dłuższy czas, może to być całkiem proste, po prostu zrobić człowieka we wszystkich wywołaniach systemu, które wyglądają tak, jakby zawierały informacje, których szukasz.

Kiedy biegnę

strace ifconfig 

Niektóre z ciekawych rozmów to:

open("/proc/net/dev", O_RDONLY)   = 6 

następnie pęczek funkcji ioctl, potwierdzające @ Payne'a odpowiedź:

ioctl(5, SIOCGIFFLAGS, {ifr_name="eth0", ifr_flags=IFF_UP|IFF_BROADCAST|IFF_RUNNING|IFF_MULTICAST}) = 0 
ioctl(5, SIOCGIFHWADDR, {ifr_name="eth0", ifr_hwaddr=84:2b:2b:b7:9e:6d}) = 0 
ioctl(5, SIOCGIFMETRIC, {ifr_name="eth0", ifr_metric=0}) = 0 
ioctl(5, SIOCGIFMTU, {ifr_name="eth0", ifr_mtu=1500}) = 0 
+2

Fajna technika! – payne

+0

Podoba mi się ta wskazówka. – Ravi

+11

+1 za odpowiedź, która pokazuje, w jaki sposób znalazłeś odpowiedź i jak zastosować technikę do innych problemów. –

7

jeden prosty sposób jest użycie funkcji popen, patrz: http://pubs.opengroup.org/onlinepubs/009696899/functions/popen.html

użyć coś jak:

FILE *fp; 

char returnData[64]; 

fp = popen("/sbin/ifconfig eth0", "r"); 

while (fgets(returnData, 64, fp) != NULL) 
{ 
    printf("%s", returnData); 
} 

pclose(fp); 
+2

Ludziom się to nie spodoba, ale jest to świetna przenośna odpowiedź, a przetaczanie za pomocą ioctls nie jest przeznaczone dla osób o słabych nerwach! –

+1

Zabawna odpowiedź. Chciałbym przegłosować, gdybyś wyposażył go również w 'awk' do analizowania wartości.Ponieważ rozwidliłeś i wywołałeś powłokę już z 'popen', sugerowałbym użycie' awk' jako klasycznego Uniksa do parsowania danych zamiast 'strtok',' strstr', itp. W C. – mctylr

8

Oto jak uzyskać adres MAC i MTU w moim kodu:

void getMACAddress(std::string _iface,unsigned char MAC[6]) { 
     int fd = socket(AF_INET, SOCK_DGRAM, 0); 
     struct ifreq ifr; 
     ifr.ifr_addr.sa_family = AF_INET; 
     strncpy(ifr.ifr_name , _iface.c_str() , IFNAMSIZ-1); 
     ioctl(fd, SIOCGIFHWADDR, &ifr); 
     for(unsigned int i=0;i<6;i++) 
      MAC[i] = ifr.ifr_hwaddr.sa_data[i]; 
     ioctl(fd, SIOCGIFMTU, &ifr); 
     close(fd); 
     printf("MTU: %d\n",ifr.ifr_mtu); 
     printf("MAC:%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",MAC[0],MAC[1],MAC[2],MAC[3],MAC[4],MAC[5]); 
    } 
+0

Co mam przekazać? w 'unsigned char MAC [6] '?? – ppumkin

+0

@ppkinkin: MAC [6] jest parametrem wyjściowym, używa go zamiast zwracanej wartości. Wpisz tam wskaźnik do własnej tablicy niepodpisanych znaków. W ten sposób: 'unsigned char outMAC [6]; getMACAddress ("eth0", outMac); ' – Youda008

5

Jest prostsze podejście. skopiowany z http://man7.org/linux/man-pages/man3/getifaddrs.3.html

#include <arpa/inet.h> 
    #include <sys/socket.h> 
    #include <netdb.h> 
    #include <ifaddrs.h> 
    #include <stdio.h> 
    #include <stdlib.h> 
    #include <unistd.h> 
    #include <linux/if_link.h> 

    int main(int argc, char *argv[]) 
    { 
     struct ifaddrs *ifaddr, *ifa; 
     int family, s, n; 
     char host[NI_MAXHOST]; 

     if (getifaddrs(&ifaddr) == -1) { 
      perror("getifaddrs"); 
      exit(EXIT_FAILURE); 
     } 

     /* Walk through linked list, maintaining head pointer so we 
      can free list later */ 

     for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) { 
      if (ifa->ifa_addr == NULL) 
       continue; 

      family = ifa->ifa_addr->sa_family; 

      /* Display interface name and family (including symbolic 
       form of the latter for the common families) */ 

      printf("%-8s %s (%d)\n", 
        ifa->ifa_name, 
        (family == AF_PACKET) ? "AF_PACKET" : 
        (family == AF_INET) ? "AF_INET" : 
        (family == AF_INET6) ? "AF_INET6" : "???", 
        family); 

      /* For an AF_INET* interface address, display the address */ 

      if (family == AF_INET || family == AF_INET6) { 
       s = getnameinfo(ifa->ifa_addr, 
         (family == AF_INET) ? sizeof(struct sockaddr_in) : 
              sizeof(struct sockaddr_in6), 
         host, NI_MAXHOST, 
         NULL, 0, NI_NUMERICHOST); 
       if (s != 0) { 
        printf("getnameinfo() failed: %s\n", gai_strerror(s)); 
        exit(EXIT_FAILURE); 
       } 

       printf("\t\taddress: <%s>\n", host); 

      } else if (family == AF_PACKET && ifa->ifa_data != NULL) { 
       struct rtnl_link_stats *stats = (struct rtnl_link_stats *)ifa->ifa_data; 

       printf("\t\ttx_packets = %10u; rx_packets = %10u\n" 
         "\t\ttx_bytes = %10u; rx_bytes = %10u\n", 
         stats->tx_packets, stats->rx_packets, 
         stats->tx_bytes, stats->rx_bytes); 
      } 
     } 

     freeifaddrs(ifaddr); 
     exit(EXIT_SUCCESS); 
    } 
Powiązane problemy