Linux 使用 C 代码获取与 ifconfig 相同的信息

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4951257/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 00:18:13  来源:igfitidea点击:

using C code to get same info as ifconfig

clinuxnetworking

提问by Ravi

Is there a way in Linux, using C code, to get the same information that "ifconfig eth0" would return? I'm interested in things like IP address, link status, and MAC address.

在 Linux 中有没有办法使用 C 代码来获取与“ifconfig eth0”返回的信息相同的信息?我对 IP 地址、链接状态和 MAC 地址等内容感兴趣。

Here's sample output from ifconfig:

下面是 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 

采纳答案by payne

Yes, ifconfigitself is written in C. :) See: http://cvsweb.netbsd.org/bsdweb.cgi/src/sbin/ifconfig/ifconfig.c?rev=1.169&content-type=text/x-cvsweb-markup

是的,ifconfig它本身是用 C 编写的。:) 参见:http: //cvsweb.netbsd.org/bsdweb.cgi/src/sbin/ifconfig/ifconfig.c?rev=1.169&content-type=text/x- cvsweb-markup

Do man netdeviceto see the details (on Linux). You use the ioctl()system call.

执行man netdevice以查看详细信息(在 Linux 上)。您使用ioctl()系统调用。

回答by Paul Rubel

One way to get to the bottom of problems like this, particularly in cases when you don't have source, is strace.

解决此类问题的一种方法,特别是在您没有源的情况下,是strace

It gives you a list of all the system calls made by any program you pass it, along with their arguments and return values. If your program just dumps some info and quits rather than running for an extended time it can be pretty straightforward to just do a man on all the system calls you see that look like they might provide the info you're looking for.

它为您提供了由您传递给它的任何程序进行的所有系统调用的列表,以及它们的参数和返回值。如果您的程序只是转储一些信息并退出而不是长时间运行,那么在您看到的所有系统调用上做一个人可能会非常简单,看起来他们可能会提供您正在寻找的信息。

When I run

当我跑

strace ifconfig

Some of the interesting calls are:

一些有趣的电话是:

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

followed by a bunch of ioctls, corroborating @payne's answer:

接着是一堆 ioctls,证实了@payne 的回答:

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

回答by Lewis R

One simple way is to use the popen function see: http://pubs.opengroup.org/onlinepubs/009696899/functions/popen.html

一种简单的方法是使用 popen 函数,请参见:http: //pubs.opengroup.org/onlinepubs/009696899/functions/popen.html

Use something like:

使用类似的东西:

FILE *fp;

char returnData[64];

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

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

pclose(fp);

回答by Behrooz

Here is how I get MAC and MTU in my code:

这是我在代码中获取 MAC 和 MTU 的方法:

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

回答by Pramod

There is simpler approach. copied from http://man7.org/linux/man-pages/man3/getifaddrs.3.html

有更简单的方法。复制自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);
   }

回答by 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] = '
parse_ioctl("eth0");
'; /* 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); }

usage :

用法 :

##代码##