Verwenden von C-Code, um dieselben Informationen wie ifconfig zu erhalten

Lesezeit: 6 Minuten

Gibt es unter Linux eine Möglichkeit, mit C-Code dieselben Informationen zu erhalten, die “ifconfig eth0” zurückgeben würde? Ich interessiere mich für Dinge wie IP-Adresse, Verbindungsstatus und MAC-Adresse.

Hier ist eine Beispielausgabe von 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 

  • ‘ifconfig’ wird seit vielen Jahren nicht mehr unter Linux gepflegt. Verwenden Sie stattdessen „ip“. serverfault.com/questions/633087/…

    – Mikemaccana

    28. August 2015 um 14:55 Uhr


Eine Möglichkeit, solchen Problemen auf den Grund zu gehen, insbesondere in Fällen, in denen Sie keine Quelle haben, ist spur.

Es gibt Ihnen eine Liste aller Systemaufrufe, die von jedem Programm, das Sie übergeben, durchgeführt wurden, zusammen mit ihren Argumenten und Rückgabewerten. Wenn Ihr Programm nur einige Informationen ausgibt und beendet wird, anstatt längere Zeit zu laufen, kann es ziemlich einfach sein, bei allen Systemaufrufen, die Sie sehen, einfach einen Mann zu machen, der so aussieht, als ob sie die gesuchten Informationen liefern könnten.

Wenn ich laufe

strace ifconfig

Einige der interessanten Anrufe sind:

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

gefolgt von einer Reihe von ioctls, die die Antwort von @payne bestätigen:

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

  • +1 für eine Antwort, die zeigt, wie Sie die Antwort gefunden haben und wie Sie die Technik auf andere Probleme anwenden können

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    9. Februar 2011 um 23:48 Uhr

  • Clever ignoriert natürlich die Tatsache, dass für die Linux ifconfig Befehl, Quelle ist leicht verfügbar.

    – mctylr

    18. Juli 2014 um 16:56 Uhr

  • Dies muss eines der besten Tools sein, die ich je gesehen habe, um zu versuchen, die Funktionalität von Befehlen und Filtern zu emulieren. Manchmal sind Sie in Eile und müssen wissen, welche Abfolge von Systemaufrufen Ihnen das bringt, was Sie tun müssen, ohne popen() aufzurufen, um den Befehl zu berappen. Einer der besten Tipps, die ich zum Thema Linux-Programmierung gefunden habe. Vielen Dank!

    – CCS

    25. November 2015 um 21:47 Uhr

Ja, ifconfig selbst ist in C geschrieben. 🙂 Siehe: http://cvsweb.netbsd.org/bsdweb.cgi/src/sbin/ifconfig/ifconfig.c?rev=1.169&content-type=text/x-cvsweb-markup

Tun man netdevice um die Details anzuzeigen (unter Linux). Sie verwenden die ioctl() Systemaufruf.

Es gibt einen einfacheren Ansatz. kopiert von 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);
   }

Benutzeravatar von Lewis R
Lewis R

Eine einfache Möglichkeit ist die Verwendung der Popen-Funktion, siehe:
http://pubs.opengroup.org/onlinepubs/009696899/functions/popen.html

Verwenden Sie so etwas wie:

FILE *fp;

char returnData[64];

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

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

pclose(fp);

So bekomme ich MAC und MTU in meinen Code:

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]);
    }

  • Was übergebe ich an die unsigned char MAC[6] ??

    – Piotr Kula

    8. Juni 2015 um 21:22 Uhr

  • @ppumkin: MAC[6] ein Ausgabeparameter ist, verwendet er ihn anstelle des Rückgabewerts. Geben Sie dort also einen Zeiger auf Ihr eigenes Array von unsigned chars ein. So was: unsigned char outMAC[6]; getMACAddress("eth0", outMac);

    – Youda008

    26. Dezember 2015 um 19:10 Uhr

  • Aber wie bekommt man den Schnittstellennamen, wenn man nur die Bindungsadresse hat?

    – Carlo Holz

    10. Juli 2019 um 15:38 Uhr

Benutzeravatar von Mahdi Mohammadi
Mahdi Mohammadi

void parse_ioctl(const char *ifname)
{
    printf("%s\n", "scarf rosari...");
    int sock;
    struct ifreq ifr;
    struct sockaddr_in *ipaddr;
    char address[INET_ADDRSTRLEN];
    size_t ifnamelen;

    /* copy ifname to ifr object */
    ifnamelen = strlen(ifname);
    if (ifnamelen >= sizeof(ifr.ifr_name)) {
        printf("error :%s\n", ifr.ifr_name);
        return ;
    }
    memcpy(ifr.ifr_name, ifname, ifnamelen);
    ifr.ifr_name[ifnamelen] = '\0';

    /* open socket */
    sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
    if (sock < 0) {
        printf("error :%s\n", "unable to open socket..");
        return;
    }

    /* process mac */
    if (ioctl(sock, SIOCGIFHWADDR, &ifr) != -1) {
        printf("Mac address: %02x:%02x:%02x:%02x:%02x:%02x\n",
                (unsigned char)ifr.ifr_hwaddr.sa_data[0],
                (unsigned char)ifr.ifr_hwaddr.sa_data[1],
                (unsigned char)ifr.ifr_hwaddr.sa_data[2],
                (unsigned char)ifr.ifr_hwaddr.sa_data[3],
                (unsigned char)ifr.ifr_hwaddr.sa_data[4],
                (unsigned char)ifr.ifr_hwaddr.sa_data[5]);
    }

    /* process mtu */
    if (ioctl(sock, SIOCGIFMTU, &ifr) != -1) {
        printf("MTU: %d\n", ifr.ifr_mtu);
    }

    /* die if cannot get address */
    if (ioctl(sock, SIOCGIFADDR, &ifr) == -1) {
        close(sock);
        return;
    }

    /* process ip */
    ipaddr = (struct sockaddr_in *)&ifr.ifr_addr;
    if (inet_ntop(AF_INET, &ipaddr->sin_addr, address, sizeof(address)) != NULL) {
        printf("Ip address: %s\n", address);
    }

    /* try to get broadcast */
    if (ioctl(sock, SIOCGIFBRDADDR, &ifr) != -1) {
        ipaddr = (struct sockaddr_in *)&ifr.ifr_broadaddr;
        if (inet_ntop(AF_INET, &ipaddr->sin_addr, address, sizeof(address)) != NULL) {
            printf("Broadcast: %s\n", address);
        }
    }

    /* try to get mask */
    if (ioctl(sock, SIOCGIFNETMASK, &ifr) != -1) {
        ipaddr = (struct sockaddr_in *)&ifr.ifr_netmask;
        if (inet_ntop(AF_INET, &ipaddr->sin_addr, address, sizeof(address)) != NULL) {
            printf("Netmask: %s\n", address);
        }
    }

    close(sock);
}

Verwendungszweck :

parse_ioctl("eth0");

  • Was übergebe ich an die unsigned char MAC[6] ??

    – Piotr Kula

    8. Juni 2015 um 21:22 Uhr

  • @ppumkin: MAC[6] ein Ausgabeparameter ist, verwendet er ihn anstelle des Rückgabewerts. Geben Sie dort also einen Zeiger auf Ihr eigenes Array von unsigned chars ein. So was: unsigned char outMAC[6]; getMACAddress("eth0", outMac);

    – Youda008

    26. Dezember 2015 um 19:10 Uhr

  • Aber wie bekommt man den Schnittstellennamen, wenn man nur die Bindungsadresse hat?

    – Carlo Holz

    10. Juli 2019 um 15:38 Uhr

1386500cookie-checkVerwenden von C-Code, um dieselben Informationen wie ifconfig zu erhalten

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy