linux - 识别c中的虚拟网络接口(interface)

标签 linux network-programming ioctl

我正在尝试查找我的设备使用 C 运行的接口(interface)。 我用 ioctl 扫描了所有接口(interface),我将结果排列为:

iface 0 ==> lo      IP = 127.0.0.1      FLAGS = 00000049    MAC: 00 00 00 00 00 00 
iface 1 ==> eth0    iface no IP         FLAGS = 00001043    MAC: 40 D6 3C 02 74 10 
iface 2 ==> eth0.1  iface no IP         FLAGS = 00001043    MAC: 40 D6 3C 02 74 10 
iface 3 ==> ra0     iface no IP         FLAGS = 00001043    MAC: 40 D6 3C 02 74 10 
iface 4 ==> br-lan  IP = 192.168.100.1  FLAGS = 00001043    MAC: 40 D6 3C 02 74 11 
iface 5 ==> apcli0  IP = 192.168.1.17   FLAGS = 00001043    MAC: 42 D6 3C 02 74 10 
iface 6 ==> mon0    iface no IP         FLAGS = 00001002    MAC: 40 D6 3C 02 74 10 

从列表中,我可以识别没有 IP 的环回、非工作接口(interface)。我仍然有两个具有相同 FLAGS 和 IP(apcli0 和 br-lan)的接口(interface)。 br-lan 是一个虚拟接口(interface)。

是否有办法识别接口(interface)是否是虚拟的(使用 C)?

这是我的代码:

    int i;
    int fd;
    int cnt = 0;
    struct ifaddrs *addrs,*tmp;
    char ibuf[256];
    struct ifreq ifr;

    fd = socket(AF_INET, SOCK_DGRAM, 0);

    getifaddrs(&addrs);

    tmp = addrs;

    while (tmp)
    {
        if ( (tmp->ifa_addr) && (tmp->ifa_addr->sa_family == AF_PACKET)) {
            printf("iface %i ==> %s\n", cnt, tmp->ifa_name);

            // get ip
            ifr.ifr_addr.sa_family = AF_INET;
            strncpy(ifr.ifr_name, tmp->ifa_name, IFNAMSIZ);

            if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
                printf("IP = %s\n", (char *)inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
            } else {
                printf("iface no IP\n");
            }

            // flags
            if (ioctl(fd, SIOCGIFFLAGS, &ifr) == 0) {
                printf("FLAGS = %08X\n", ifr.ifr_flags);
            } else {
                printf("iface no flags\n");

            }

            // mac addr
            if (ioctl(fd, SIOCGIFHWADDR, &ifr) == 0) {
                memcpy(ibuf, ifr.ifr_hwaddr.sa_data, 6);
                printf("MAC: ");
                for (i=0; i<6; i++) {
                    printf("%02X ", ibuf[i] & 0xFF);
                }
                printf("\n");
            } else {
                printf("iface no mac\n");

            }

            cnt++;
        }
        tmp = tmp->ifa_next;
    }
    freeifaddrs(addrs);

谢谢。

最佳答案

我不认为这对于 getifaddrs() 返回的信息是可能的,因为没有 SIOCGIFFLAGS 指示设备是虚拟的。例如,您可以通过检查 iface->ifa_flags 中的 IFF_LOOPBACK 标志(loopback 是一个虚拟接口(interface))找到一些虚拟设备,但是没有结构中的信息,具体说明设备是物理设备还是虚拟设备。

对于相当新的 Linux 内核(不确定启动内核,但它至少必须提供一个 sysfs),我相信这可以通过检查 /sys/class/net -- 目录来确定这里将代表 ifconfiggetifaddrs() 报告的接口(interface),并且将被符号链接(symbolic link)到 /sys/devices/platform 中的设备(物理设备)或 /sys/devices/virtual(虚拟设备)。我不知道在“常规 C”中执行此操作的干净方法(使用良好的理智函数调用,然后检查物理或虚拟标志),但似乎可以通过检查 中的目录结构来实现/sys.

编辑:看起来 pci 设备是物理设备,也可以显示在 /sys/devices/pci0000:00 或类似的目录下,因此并非所有物理设备都会在 /sys/devices/physical,因此更好的检查是 /sys/class/net 目录没有符号链接(symbolic link)到 /sys/devices/virtual目录...

关于linux - 识别c中的虚拟网络接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50538099/

相关文章:

python - 使用\r 并打印一些文本后,如何清除控制台中的一行?

linux - Bash 脚本退出清理

c# - 序列化和发送 Protocol Buffers 消息

c - 如何在 Linux 中使用 ioctl(原始分区)正确刷新磁盘缓存

Linux 字符驱动程序 : blocking ioctl call

javascript - 在 Linux 服务器端缩小并加入 CSS 和 JS 文件

linux - Linux 中的 IO 多路复用

c - 在 C 中通过 TCP 发送和接收整数值

network-programming - 使用 SNMP LLDP 查找邻居

c - Linux 输入设备读取 ioctl(EVIOCGKEY()) 与 read(input_event)