在c中识别虚拟网络接口

Posted

技术标签:

【中文标题】在c中识别虚拟网络接口【英文标题】:Identify virtual network interface in c 【发布时间】:2018-05-25 23:49:31 【问题描述】:

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

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 

我使用 getifaddrs() 获取接口列表,然后使用 ioctl(使用 SIOCGIFADDR 的 IP)、(使用 SIOCGIFFLAGS 的标志)枚举 net_device_flags 和(使用 SIOCGIFHWADDR 的 mac)。

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

是否可以确定接口是否为虚拟接口(使用 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);

谢谢。

【问题讨论】:

请出示您的代码。 【参考方案1】:

我认为getifaddrs() 返回的信息不可能做到这一点,因为没有SIOCGIFFLAGS 表明设备是虚拟的。例如,您可以通过检查IFF_LOOPBACK 中的IFF_LOOPBACK 标志(环回是一个虚拟接口)来找到一些虚拟设备,但是结构中没有具体说明设备是物理设备还是物理设备的信息。虚拟的。

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

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

【讨论】:

是的。对。最好深入研究/sys/class/net。我认为如果我单独使用 C 会很复杂。

以上是关于在c中识别虚拟网络接口的主要内容,如果未能解决你的问题,请参考以下文章

虚拟机网卡显示未识别的网络,求解决!?

请问如何给虚拟机设置多个网络接口??

Mac OS X 中的虚拟网络接口

linux虚拟机怎么查看自己新设的ip地址是不是生效

☀️苏州程序大白解析Linux 中的虚拟网络接口☀️《❤️记得收藏❤️》

kali linux: 网卡监听及扫描网络