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

Rav*_*avi 29 c linux networking

Linux中是否有一种方法可以使用C代码获取"ifconfig eth0"返回的相同信息?我对IP地址,链接状态和MAC地址等感兴趣.

这是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 
Run Code Online (Sandbox Code Playgroud)

Pau*_*bel 77

解决这类问题的一个方法,特别是在你没有源代码的情况下,就是strace.

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

我跑的时候

strace ifconfig
Run Code Online (Sandbox Code Playgroud)

一些有趣的电话是:

open("/proc/net/dev", O_RDONLY)         = 6
Run Code Online (Sandbox Code Playgroud)

接着是一堆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
Run Code Online (Sandbox Code Playgroud)

  • +1表示您如何找到答案的答案,以及如何将该技术应用于其他问题 (12认同)
  • 好技术! (3认同)
  • 聪明,当然它确实忽略了这样一个事实:对于**Linux**`ifconfig`命令,[source](http://sourceforge.net/projects/net-tools/)随时可用. (2认同)
  • 这必须是我见过的最好的工具之一,用于尝试模拟命令和过滤器的功能。有时你很匆忙,需要知道什么样的系统调用序列可以让你在不调用 popen() 来执行命令的情况下完成你需要做的事情。我有幸找到了有关 Linux 编程的最佳技巧之一。非常感谢! (2认同)

pay*_*yne 36

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

不要man netdevice看细节(在Linux上).您使用ioctl()系统调用.


Beh*_*ooz 9

以下是我在代码中获取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]);
    }
Run Code Online (Sandbox Code Playgroud)


Pra*_*mod 9

有更简单的方法.复制自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);
   }
Run Code Online (Sandbox Code Playgroud)


Lew*_*s R 8

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

使用类似的东西:

FILE *fp;

char returnData[64];

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

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

pclose(fp);
Run Code Online (Sandbox Code Playgroud)

  • 人们不会喜欢它,但它是一个很好的便携式答案,使用ioctls滚动你自己不适合胆小的人! (2认同)